Prévia do material em texto
criadordoZabbix!
.,. ~ASPORT
• ... !151
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Janssen dos Reis Lima
Consumindo a
API doZabbix
comPython
Prefácio de Alexei Vladishev criador do Zabbixl
., ~SPORT
** "
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Copyr.ight© 2016 por Brasport Livros e Multimídia Ltda.
Todos os direitos reservados. Nenhuma parte deste livro poderá ser
reproduzida, sob qualquer meio, especialmente em fotocópia (xerox),
sem a permissão, por escrito, da Editora.
Para uma melhor visualização deste e-book sugerimos que mantenha
seu software constantemente atualizado.
Editor: Sergio Martins de Oliveira
Diretora Editorial: Rosa Maria Oliveira de Queiroz
Gerente de Produção Editorial: Marina dos Anjos Martins de Oliveira
Editoração Eletrônica: SBNigri Artes e Textos Ltda.
Capa: Trama Criações
Produçao de e-pub: SBNigri Artes e Textos Ltda.
Técnica e muita atenção foram empregadas na produção deste livro.
Porém, erros de digitação e/ou impressão podem ocorrer. Qualquer
dúvida, inclusive de conceito, solicitamos enviar mensagem para
brasport@brasport.com.br, para que nossa equipe, juntamente com o
autor, possa esclarecer. A Brasport e o(s) autor(es) não assumem
qualquer responsabilidade por eventuais danos ou perdas a pessoas
ou bens, originados do uso deste livro.
ISBN Digital: 978-85-7452-781-9
BRASPORT Livros e Multimídia Ltda.
Rua Pardal Mallet, 23 - Tijuca
20270-280 Rio de Janeiro-RJ
Tels. Fax (21) 2568.1415/2568.1 507
e-mails:
marketing@brasport.com.br
vendas@brasport.com.br
editorial@brasport.com.br
site: www.brasport.com.br
Filial
Av. Paulista, 807 - conj. 915
01311-100- São Paulo-SP
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
Agradecimentos
Agradeço principalmente a Deus, por me dar forças para que eu
conseguisse ter calma e paciência para concluir este projeto. Foram
longas noites dedicadas a este trabalho.
A minha esposa Carla, por toda a sua dedicação e carinho que
tem pela nossa família. Agradeço de coração por sempre me
incentivar nos meus estudos e por compreender minha ausência
em certos momentos. Você é muito especial.
Agradeço também à equipe de desenvolvimento do Zabbix, não
apenas por manter esta excelente ferramenta em constante
atualização, mas também por mantê-la bem documentada,
sobretudo a parte da API.
Agradeço também ao editor da Brasport, Sergio Martins, e à
gerente de produção editorial, Marina, por acreditarem no meu
trabalho e terem me dado mais uma oportunidade de publicar outro
livro.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
O todo é maior do que a simples soma das suas parles.
(Aristóteles)
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Apresentação
A API do Zabbix permite recuperar e modificar configurações do
ambiente de monitoramento, além de fornecer acesso a dados
históricos. Ela pode ser utilizada tanto por profissionais de
infraestrutura como por desenvolvedores.
Para profissionais de infraestrutura que já dominam a ferramenta,
o uso da API se faz necessário para automatizar tarefas rotineiras,
com o propósito de acelerar a execução dessas tarefas e diminuir
as probabilidades de configurações incorretas. Já o uso da API
para desenvolvedores se dá pela necessidade de gerar novas
aplicações e emitir relatórios personalizados para a área gerencial,
devido ao fato de a ferramenta não disponibilizar isso por meio da
sua interface web.
Sabemos que, em muitos casos, o departamento de TI é visto
como burocrático e sempre trabalhando na parte operacional. Em
vez de ficar apenas na resolução de problemas e na
implementação de novas tecnologias, esse departamento pode
disponibilizar dados sobre o negócio através do monitoramento do
ambiente, para que a área gerencial possa consumir esses dados
com os relatórios e tomar decisões através das informações
obtidas. Isso vai transformar o departamento de TI em uma
plataforma de negócios, pois irá assumir um papel estratégico e, ao
mesmo tempo, será visto como um departamento que agrega valor
ao negócio, e não apenas como um que opera a tecnologia.
Esta obra apresentará a API do Zabbix e tentará passar aos
leitores como utilizar os métodos disponibilizados pela API para
gerar seus próprios relatórios e integrar o Zabbix com outras
ferramentas. Serão demonstrados exemplos práticos de como
utilizar os métodos e como formatar a saída das requisições para
serem usadas em relatórios. O objetivo principal da API do Zabbix
não é desenvolver dashboards, e sim entregar informações
requisitadas através da utilização dos métodos. Para fazer
dashboards você terá que possuir habilidades de desenvolvimento
web, passando as informações consumidas pela API para exibir
nesses sistemas. Portanto, não desanime se você chegou até aqui
achando que ao utilizar a API do Zabbix você iria desenvolver um
dashboard. A API é mais que isso. Ela permite que você estenda e
potencialize o uso dos serviços disponibilizados pela ferramenta.
Resolvi escrever este livro após ter lançado o curso
"Programação com a API do Zabbix", que teve uma grande
repercussão na comunidade. Por conta disso, vi que não eram
poucas as pessoas com interesse em aprender a API do Zabbix,
haja vista que não temos documentação sobre o assunto na língua
portuguesa.
Espero que os leitores tirem proveito das informações aqui
apresentadas e consigam explorar ao máximo os recursos
fornecidos pela API do Zabbix e desenvolvam seus próprios
produtos, sejam eles relatórios ou integrações.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Sobre o Livro
Este livro está dividido em 11 capítulos:
)> Visão Geral: neste capítulo serão apresentadas informações
básicas sobre a API do Zabbix, sua estrutura e funções
fornecidas, além de uma rápida passagem sobre JSON.
)> Bibliotecas: neste capítulo veremos como preparar o
ambiente para o desenvolvimento dos nossos códigos e com
qual biblioteca da API do Zabbix trabalharemos.
)> Primeiros Passos: neste capítulo teremos o nosso primeiro
contato com uma requisição à API do Zabbix.
)> Referências e Notações: este capítulo apresentará os tipos
de dados que são suportados pela API do Zabbix.
)> Classes e Métodos da API: neste capítulo veremos alguns
métodos disponíveis na API do Zabbix. Em todos os métodos
veremos exemplos práticos de consumo de dados da API.
)> Ferramentas para Formatação e Validação de JSON: este
capítulo apresentará algumas ferramentas para a formatação
das requisições no formato JSON, para que o código fique
mais limpo e de fácil leitura.
)> Formatando a Saída das Requisições: neste capítulo
aprenderemos como formatar as saídas das requisições, com
o objetivo de consumir os valores dos objetos da API.
)> Automatizando Tarefas: neste capítulo veremos exemplos
práticos que irão lhe garantir um tempo extra na execução de
suas tarefas.
)> Gerando Relatórios: mais um capítulo de exemplos práticos
mostrando a geração de alguns relatórios com os dados
consumidos da API.
)> Dicas de Projetos com a API: este capítulo visa discutir
ideias para projetos com a API do Zabbix e também
apresentar algumas bibliotecas que serão úteis no
desenvolvimento desses projetos.
)> Dicas Importantes: este capítulo fecha o livro com algumas
dicas que não podem ser ignoradas e que irão ajudar o leitor
a buscar mais informações para se aperfeiçoar na API do
Zabbix.
Configurações e versões
Todos os testes e comandos mostrados nesta obra foram
executados nas seguintes configurações de sistema:
)> Processador: Intel Core i7
)> Memória: 8 GB
)> Sistema operacional: Debian 8 64 bits
)> Kemel: 3.1 .1.1
)> versão do Python: 2.7.9
)> Versão do Zabbix: 2.4.6
Reprodução de testes e comandos
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Os testes e comandos propostos nesta obra devem ser
executados comextrema cautela e não é recomendado reproduzi-
los em ambientes de produção, haja vista que muitos dos
comandos são usados para demonstrar alterações de
configurações no ambiente usando a API do Zabbix.
Portanto, recomendo criar um ambiente de testes para executar
os comandos e códigos demonstrados nesta obra.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Sobre o Autor
Janssen dos Reis Lima possui 18 anos de experiência na área
de TI. Bacharel em Sistemas de Informação pela FeMASS/UFF,
especialista em Administração em Redes Linux pela UFLA e
mestrando em Sistemas Computacionais pela UFF. Atualmente
ocupa o cargo de Analista de Sistemas no Grupo de Inferência de
Reservatório, no LENEP/UENF. Utiliza Python como ferramenta de
desenvolvimento e pesquisa. Fundou a empresa Conectsys,
especializada em treinamentos, consultoria e suporte técnico em
Zabbix, tendo lançado cursos exclusivos de programação com API
do Zabbix e API do Zabbix para Sysadmin. Possui especial
interesse em computação de alto desempenho, gerência de redes e
virtualização, sempre trabalhando com software open source. É
autor do livro "Monitoramento de Redes com Zabbix", também
publicado pela Brasport.
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
Prefácio
Dear .readers,
Zabbix is a well-known open source enterprise level monitoring
solution. The word "enterprise" means that Zabbix can be easily
integrated with third party systems and may co-exist nicely with
other platforms. Undoubtedly, Zabbix API is the most important
functionality when it comes to implementation of integration plans.
The API plays a major role in any automation logic by allowing to
communicate with Zabbix not only from higher levei languages like
Java, Perl, Python, Go, but also doing direct API calls from
command line.
The book describes Zabbix API in great details and provides
numerous examples on how to get most of the API. 1 am sure that
the book will be a great help for those wanting to bring use and
understanding of Zabbix to the next level.
A lexei Vladishev, creator of Zabbix
TRADUCÃO:
Caros leitores,
Zabbix é uma solução open source de monitoramento de nível
empresarial bem conhecida. O termo "empresarial" significa que
Zabbix pode ser facilmente integrado com sistemas de terceiros e
pode coexistir muito bem com outras plataformas. Sem dúvida, a
API do Zabbix é a funcionalidade mais importante quando se trata
de execução de planos de integração. A API desempenha um papel
importante em qualquer lógica de automação, permitindo que se
comunique com Zabbix não apenas a partir de linguagens de alto
nível, como Java, Perl, Python, Go, mas também fazendo
chamadas diretas à API a partir de linha de comando.
O livro descreve a API do Zabbix em grandes detalhes e fornece
inúmeros exemplos de como extrair o máximo da API. Tenho
certeza de que o livro vai ser uma grande ajuda para aqueles que
querem levar o uso e a compreensão do Zabbix para o próximo
nível.
Alexei Vladishev, criador do Zabbix
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Sumário
Introdução
1. Visão Geral
1.1. API do Zabbix
1.2. Estrutura
1.3. Funções fornecidas pela API
1.3.1. Monitoramento
1.3.2. Configuração
1.3.3. Administração
1.3.4. Informação da API
1.4. Execução das requisições
1.5. Um pouco sobre JSON
2. Bibliotecas
2.1 . Vantagens de usar uma biblioteca
2.2 . Qual biblioteca escolher?
2.3. Preparando o ambiente para
desenvolvimento em Linux
2.4. Preparando o ambiente para
desenvolvimento em Windows
2.5. Biblioteca zabbix-api
2.5.1 . Ambiente Linux
2.5.2. Ambiente Windows
3. Primeiros Passos
3.1. Criando usuário para acessar a API
3.2. Montando a estrutura padrão
3.3. Obtendo IDs e nomes dos hosts
3.4. Organizando os dados
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
4. Referências e Notações
4.1. Etiquetas de propriedades
4.2. Objetos
4.3. Parâmetros comuns do método "get"
5. Classes e Métodos da API
5.1. API lnfo
5.1.1. Referências do objeto
5.1.2. Métodos disponíveis
5.1.2.1. apiinfo.version
5.2. Host
5.2.1. Referência do objeto
5.2.2. Métodos disponíveis
5.2.2.1. host.create
5.2.2.2. host.massadd
5.2.2.3. host. isreadable
5.3. Host Group
5.3.1. Referências do objeto
5.3.2. Métodos disponíveis
5.3.2.1. hostgroup.delete
5.3.2.2. hostgroup.massupdate
5.4. Template
5.4.1. Referências do objeto
5.4.2. Métodos disponíveis
5.4.2.1. template.update
5.4.2.2. template.massremove
5.5. Item
5.5.1. Referências do objeto
5.5.2. Métodos disponíveis
5.5.2.1. item.update
5.6. Trigger
5.6.1. Referências do objeto
5.6.2. Métodos disponíveis
5.6.2.1. trigger.adddependencies
5.7. History
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
5.7.1. Referências do objeto
5.7.2. Métodos disponíveis
5.7.2.1. history.get
5.8. Event
5.8.1. Referências do objeto
5.8.2. Métodos disponíveis
5.8.2.1. event.get
5.8.2.2. event.acknowledge
5.9. Alert
5.9.1. Referências do objeto
5.9.2. Métodos disponíveis
5.9.2.1. alert.get
5.1 O. lt Service
5.10.1. Referências do objeto
5.10.2. Métodos disponíveis
5.10.2.1. service.getsla
6. Ferramentas para Formatação e Validação
de JSON
6.1. Zapix
7. Formatando a Saída das Requisições
7.1. Formatando a saída da requisição do
exemplo mostrado no tópico 5.7.2.1
7.2. Formatando a saída de requisições que se
relacionam
7.3. Convertendo datas
8. Automatizando Tarefas
8.1 . Desabilitar automaticamente itens não
suportados
8.2 . Cadastrar hosts automaticamente a partir
de uma lista em arquivo
8.3. Montar árvore de serviços de TI
automaticamente
8.3.1. Função obterGrupos
8.3.2. Função obterGrupold
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
8.3.3. Função obterHosts
8.3.4. Função obterHostld
8.3.5. Função obterTriggersHosts
8.3.6. Função obterltens
8.3.7. Função obterltemTriggerld
8.3.8. Função criarServicosPai
8.3.9. Função obterServicosPai
8.3.1 O. Função criarServicosFilho
8.3.11. Função obterServicosFilho
8.3.12. Função criarltensServicos
8.3.13. Função obterServicos
8.3.14. Função removerArvoreServicos
8.3.15. Função criarArvoreServicos
9. Gerando Relatórios
9.1. Relatório de itens não suportados
9.2. Relatório de agentes do Zabbix
desatualizados
9.3. Relatório top 1 O CPU
9.4. Relatório dos incidentes não resolvidos
1 O. Dicas de Projetos com a API
10.1. Integração com software de terceiros
10.2. Geração de gráficos e relatórios em PDF
10.2.1. Matplotlib
10.2.2. Bokeh
10.2.3. Reportl ab
10.2.4. PyGal
10.3. Envio de relatórios por e-mail
11. Dicas Importantes
11.1. Habilitando o log da biblioteca zabbix-api
11.2. Timeout das requisições
11.3. Procure threads em fóruns e listas de
discussão
11.4. Leia a documentação oficial
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Referências Bibliográficas
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Introdução
API (Applícatíon Programmíng Interface) é uma forma simples de
prover serviços em um formato comum e de fácil entendimento.
Apesar de seu uso ser comum na comunidade de desenvolvedores,
qualquer indivíduo com conhecimento básico de programação pode
se aventurar em utilizar uma API.
Seja qual for a necessidade, desde uma simples integração para
autenticação de um site com uma rede social, passando por uma
plataforma de pagamentos integrada a uma loja virtual até a
emissão de relatórios gerenciais em um sistema interno de uma
empresa, tudo isso é possível porque uma API é composta por uma
serie de métodos e funções que permitem utilizar as
funcional idades de um software sem a necessidade de conhecer a
sua implementação, como, por exemplo, em que linguagem de
programação foi desenvolvida, como é a estrutura da base de
dados etc. Portanto, ao utilizaruma API, estamos apenas
interessados em consumir os serviços disponibilizados pela
aplicação, seja para integrar com software de terceiros, automatizar
rotinas ou criar novas aplicações.
Resumindo, uma aplicação que disponibiliza uma API abre portas
para novos mercados e permite o desenvolvimento de novos
produtos e serviços.
Alguns exemplos típicos de uso de uma API:
)> Permitir a geração de relatórios customizados a partir dos
dados do sistema.
)> Integrar uma loja virtual com uma plataforma de pagamento
para que o processo seja transparente para o usuário.
)> Monitorar a audiência da empresa em redes sociais: quantas
curtidas, quantos comentários etc.
)> Entre outros.
Nesta obra o leitor aprenderá a consumir a API do Zabbix com a
linguagem de programação Python. Portanto, nem todos os
exemplos citados anteriormente aplicam a API do Zabbix.
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
1
Visão Geral
A API do Zabbix foi introduzida a partir da versão 1.8. Uma das
vantagens em utilizar a API do Zabbix é estender as possibilidades
criadas pelo armazenamento dos dados coletados em sua base de
dados. E uma dessas possibilidades inclui a emissão de relatórios
personalizados que não estão presentes em sua interface web.
Assim como desenvolvedores poderão tirar proveito da API,
administradores de sistemas também poderão utilizá-la para
automatizar tarefas repetitivas e ganhar um extra de seu precioso
tempo.
1.1. API do Zabbix
A API do Zabbix permite recuperar e modificar configurações do
Zabbix via programação, além de fornecer acesso a dados
históricos.
É amplamente utilizado para:
)> Criar novas aplicações para trabalhar com Zabbix.
)> Fazer integração com software de terceiros.
)> Automatizar tarefas rotineiras.
A API do Zabbix é baseada na web e é fornecida como parte da
interface web. A imagem a seguir mostra onde a API do Zabbix está
presente em sua arquitetura.
Interface do
, .
usuano
1 ,
Frontend API
Zabi
Servidor Web
,.- -.......
.......__ _,,
- -,. SGBD ~
Para utilizar a API, é preciso que a interface web do Zabbix esteja
disponível. Uma vez que o usuário invoque um método da API, o
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Zabbix se encarrega de obter os dados ou executar processos de
acordo com o método utilizado.
A API do Zabbix utiliza o protocolo JSON-RPC 2.0 e consiste em
um conjunto de métodos separados que são usados para fazer
requisições e receber respostas, ambas codificadas usando o
formato JSON.
Mais informações sobre o protocolo JSON podem ser
encontradas na página de especificação do protocolo, disponível
em http://www.jsonrpc.org/specification, e na página de introdução
ao formato JSON, disponível em http://json.org/.
A seguir, um exemplo de requisição no formato JSON:
"j sonrpc": "2. O",
"met hod": "user.login",
" p arams": {
} I
"user": "Adrnin",
"password": "zabbix"
"id ": 1,
"auth": nul l
E um exemplo de resposta no formato JSON:
" j sonrpc": "2. O",
"result": "0424bd59b807674191e7d77572075f33",
" id" : 1
O diagrama a seguir representa o fluxo de dados de requisição à
API do Zabbix:
Interface do
usuário
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
L user.login >
Token de auten~
[ host.get >
Ustqem dos hosts
Outros métodos
[User.logout >
--------reGjuisição, no qual receberemos a listagem com os dados dos
ob{etos requisitados, ou seja, uma listagem com os hosts
cailastrados no Zabbix. Caso não seja invocado outro método, a
seI
1
são deverá ser finalizada com o método user.logout.
J ntes da implementação da API do Zabbix, não existia nenhuma
ferramenta para controlar o Zabbix fora da interface web, exceto
executar consultas diretamente na base de dados, o que não é
mJito seguro.
ZABBIX
API
1 .. Estrutura
t API consiste em métodos que são nominalmente agrupados
e"l APls separadas, também referenciadas como classes. Cada
método executa uma tarefa específica. Por exemplo, o método
hoÍ1st.create pertence à classe host e é usado para criar novos
ho ts.
maioria das classes contém pelo menos quatro métodos: get,
cryate, update e detete para recuperar, criar, atualizar e excluir
da~os , mas algumas das APls podem fornecer um conjunto
totr lmente diferente de métodos.
t estrutura completa de todas as APls disponibilizadas pelo
Zar bix é encontrada na URL https://www.zabbix.com
/d~cumentation/2 .4/manual/api , onde são mostradas em árvore as
re_frências dos métodos. A figura a seguir exibe a listagem com
--------tõêlas as classes disponíveis na API do Zabbix:
A autenticação (método user.login) é um passo obrigatório para
obter o token de autenticação. Com o token de autenticação,
teremos a permissão de invocar qualquer método fornecido pela
API. Na imagem do fluxo de dados, o método host.get é uma nova
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
B ·17. API
1 é Method reference
m Actioo
m Alert
r:b- API lnfo
f!!-Appllcation
!B- Configuration
&Oiscovered host
E!I Discovered service
m Discovery ched
e Oisw11erv rule
1&-E11ent
m Gr.iph
IB Graph item
E!J-Graph prototvpe
~Hístorv
ffi..Host
m- Host group
m- Host interface
r:b- Host prototype
IB lcon map
E!l-lmage
&Item
1±1-Rem prototype
oo- rr service
ei UD rule
fB Maintenance
ijrMap
IB Media
&Media tvpe
& Proxy
rB Screen
~Screen Item
fil S<rlpt
r:b- Template
m- Template screen
00-Template screen item
&Tngger
& Trlgger prototype
&User
s-User group
e-user macro
m Web scenarlo
. - Appendlx 1. Reference coou»
f....Appendix 2. Changes from 2 ..
L_zabbix API changes in 2.4
1.3. Funções fornecidas pela API
Neste tópico, teremos uma visão geral sobre as funções
fornecidas pela API. As funções são as seguintes:
)> Monitoramento
)> Configuração
)> Administração
)> Informação da API
1.3.1. Monitoramento
Esta função nos permite ter acesso ao histórico e a outros dados
recolhidos durante o monitoramento. Podemos recuperar:
)> Dados históricos:
o Obter dados para apresentação ou processamento
adicional.
)> Eventos:
o Obter eventos para um gerenciamento mais flexível ou
o Integrar com ferramentas de terceiros.
)> Monitoramento de serviços:
o Obter informações sobre disponibilidade de qualquer
serviço de TI (SLA).
Podemos associar esta função ao menu Monitoring da interface
web do Zabbix, exibido na imagem a seguir:
1.3.2. Configuração
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Esta função nos permite gerenciar a configuração de
monitoramento do sistema, como: criar, atualizar, configurar,
habilitar/desabilitar, associar/desassociar etc. Podemos gerenciar:
)- Hosts e grupos de hosts
)- Itens e aplicações
)- Trigger
)- Gráficos
)- Templates
)- Exportação e importação
)- Descoberta de baixo nível (low-/eve/ discovery- LLD)
)- Telas (screens)
)- Ações e alertas
)- Serviços de TI
)- Mapas
> Monitoramento web
)- Descoberta de rede (network discovery)
Podemos associar esta função ao menu Configuration da
interface web do Zabbix, exibido na imagem a seguir:
o Configurar tipos de mídia.
o Maneiras como o usuário receberá alerta etc.
> Geral:
o Alertar para configurações globais do sistema.
)- Proxies:
o Gerenciar proxies utilizados na configuração do
monitoramento.
)- Scripts:
o Configurar e executar scripts para ajudar em tarefas
pontuais.
Podemos associar esta função ao menu Administration da
interface web do Zabbix, exibido na imagem a seguir:
1.3.4. Informação da API
Esta função nos permite obter a versão da API do Zabbix, cujos
recursos específicos podem ser utilizados por uma aplicação. A
partir da versão 2.0.4 do Zabbix, a versão da API equivale à mesma ..... ~~~~~~~~~~~~~--~--.
1.3.3. Administração
Esta função nos permite alterar configurações da administração
do sistema. Podemos manipular configurações de:
suários:o Atribuir grupos e conceder permissões.
ver.são do Zabbix que estiver em execução em seu servidor.
1.4. Execução das requisições
Uma vez que você configura a interface web, você pode usar
requisições HTTP para chamar a API. Para fazer isso, você precisa
enviar solicitações HTTP POST para o arquivo api_jsonrpc.php,
localizado na raiz do frontend do Zabbix. Vejamos um exemplo para
invocar o método apiinfo.version, que nos retorna a versão do
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Zabbix instalado no sistema:
POST http://localhost/zabbix/api_jsonrpc.ph p
HTTP/1.1
Content-Type: application/json-rpc
{"jsonrpc":"2. 0","method":"apiinfo.version","id":l,"auth" : null,
"params": { } }
O pedido deve ter o cabeçalho Content-Type definido como um
desses valores:
);> application/json-rpc
);> application/json
);> application/jsonrequest
Lembre-se de que a sua interface web deverá estar acessível;
caso contrário, você não obterá respostas para as requisições
solicitadas.
Você pode usar qualquer cliente HTTP ou uma ferramenta de
teste JSON-RPC para executar as requisições à API manualmente.
Vejamos um exemplo usando o comando curl:
# curl -X POST -H 'Content-Type:
application/ j son' - d ' {"params": {"password" :
Vamos explicar algumas opções da requisição feita:
);> params: parâmetros que serão passados para o método da
API.
);> jsonrpc: versão do protocolo utilizado pela API.
);> method: o método da API que será chamado.
);> id: identificador arbitrário do pedido.
);> auth: token de autenticação para o usuário.
Como vimos no tópico 1.1 , o método user.login é o primeiro que
devemos usar antes de invocar qualquer outro método da API, pois,
da mesma forma que precisamos fazer login para ter acesso à
interface web do Zabbix, faz-se necessário fazer login via API para
obter um token de autenticação, que será necessário para realizar
as demais requisições. Suponha que faremos login com o usuário
administrador Zabbix padrão (usuário: Admin, senha: zabbix). A
resposta JSON será parecida com a saída a seguir:
{"jsonrpc":"2.0","result":"cbd7e3ad4678761ee9d4f300
Já com o token de autenticação, podemos fazer qualquer
requisição, como, por exemplo, consultar todos os hosts
cadastrados:
"zabbix", "user": "Admin" } , # curl -X POST -H 'Content-Type:
"j sonrpc": "2. O", "method": "user. login",
"auth ": null,
"id" : 1}' h ttp://localhost/zabbix
/ api_jsonrpc.php
application/ json' -d
' {"params" : {"output": "shorten", "host": "Zabbix
server", "limit": O}, "j sonrpc": "2. O", "method":
"host.get", "auth":
"cbd7e3ad4678761ee9d4f30000a5f0f0", "id" : 1 }'
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
h ttp : //localhost/ zabbix/ a p i_j sonrpc .php
O retorno será:
{" j sonr pc":"2. 0","result ": [ {"hostid":"l0106" },
{"hostid ":"l0109"}, {"hostid ":"l 0084"},
{"hostid ":"l0107"}, {"hostid º:"l0110" }],"id":l }
Observe que escrever no formato JSON e definir diretamente a
autenticação e id toda vez que for fazer uma requisição tem um
custo, e o retrabalho é doloroso. Por isso, escrever códigos usando
uma biblioteca com implementação da API é uma opção a ser
usada.
1i5. Um pouco sobre JSON
Apenas para ficar claro o entendimento sobre JSON, explicarei
como a sua estrutura está constituída. Ela é formada por:
);:- Uma coleção de pares nome/valor, caracterizada como um
object.
);:- Uma lista ordenada de valores, caracterizada como um array.
Os dados são apresentados nas seguintes formas:
1. Conjunto desordenado de pares nome/valor: um objeto
começa com {(abre chave) e termina com} (fecha chave). Cada
nome é seguido por : (dois pontos) e os pares nome/valor são
seguidos por , (vírgula), conforme podemos observar na figura a
seguir:
nome
Exemplo:
{
"ou tput": "extend",
"sortfield": "narne",
"sortorder": "DESG"
valor
2. Coleção de valores ordenados: o array começa com [ (abre
colchete) e termina com ] (fecha colchete). Os valores são
separados por , (vírgula), conforme podemos observar na figura
a seguir:
valor
Exemplo:
13,
32
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
2
Bibliotecas
Para o desenvolvimento de aplicações com a API do Zabbix,
sugiro que o leitor use uma das bibliotecas mantidas pela
comunidade. Existem bibliotecas para trabalhar com a API do
Zabbix nas seguintes linguagens e ferramentas:
)> Python
)> Ruby
)> Perl
)> Java
)> PHP
)> JavaScript
)> e#
)> Go
)> PowerShell
)> Zabcon
As bibliotecas e ferramentas podem ser obtidas neste link:
http:f/zabbix.org/wiki/Docs/api/libraries.
E é aqui que chegamos ao primeiro ponto de partida para os não
desenvolvedores. Esta obra tem como um dos objetivos mostrar
que não é preciso ser nenhum experl em desenvolvimento de
software para consumir a API do Zabbix (eu digo não apenas do
Zabbix, mas de qualquer outro software que disponibiliza uma API)
- e também não importa qual biblioteca será usada para você
desenvolver seus códigos. Vimos no exemplo anterior o uso do
comando curl. Posso concluir que você é capaz de usar a API do
Zabbix facilmente criando scripts em Shell Linux.
O segredo da programação em APls está em conhecer os
métodos e objetos que ela oferece, e não a linguagem de
programação. É como se fosse outra linguagem de programação.
Devemos estudá-la para tirar ao máximo as funcional idades que
foram implementadas.
2.1. Vantagens de usar uma biblioteca
A época de ficar reinventando a roda já passou faz tempo. Temos
que ganhar tempo. Isso significa que devemos aproveitar uma ideia
já pronta e reutil izá-la
Evidentemente, cada um pode criar sua biblioteca para utilizar os
métodos disponibilizados pela API, até porque nem todas as
bibliotecas têm acesso a todos os recursos. Portanto, assim que já
estiver mais adaptado com a API do Zabbix, você poderá tirar
conclusões sobre se determinada biblioteca atende ao que você
deseja consumir da API. Caso nenhuma lhe atenda, é hora de
desenvolver a sua biblioteca.
2.2. Qual biblioteca escolher?
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
A biblioteca que eu recomendo para os nossos estudos é a
disponibilizada no link https://github.com/gescheit/scripts
/tree/master/zabbix, que sempre atendeu às minhas necessidades,
além de ser constantemente atualizada sempre que surge uma
mudança na API do Zabbix.
Essa biblioteca é conhecida como zabbix-api. Ela foi
desenvolvida em Python e tem suporte desde a versão 1.8 do
Zabbix, funcionando nas versões 2 e 3 do Python.
Não se preocupe se você nunca estudou essa linguagem de
programação. Analisando os códigos desta obra, você começará a
se familiarizar com a linguagem e verificará que ela é de fácil
entendimento.
2.3. Preparando o ambiente para
desenvolvimento em Linux
O Python já vem instalado por padrão nas distribuições
GNU/Linux na versão 2.7. Para o desenvolvimento de requisições
básicas, nós podemos utilizar o próprio console do Python ou
gravar scripts com a extensão .py para executar os comandos.
Para desenvolvimento de código com o propósito que nós temos
aqui, que é automatizar tarefas e criar nossas próprias aplicações,
é recomendado o uso de uma IDE para organizar mais o código e
também ser possível fazer o debug em busca de erros. Utilizaremos
a Spyder, uma IDE conhecida para desenvolvimento em ambientes
científicos. O site do projeto é https://github.com/spyder-ide.
Para instalarmos a Spyder em ambiente Linux, utilizamos o
utilitário apt-get em sistemas baseados em Debian.
# a p t-get i nsta ! ! s pyder - y
Após a instalação ser concluída, a IDE estará disponibilizada no
menu Desenvolvimento da sua interface ou através da execução
do comando spyder, via terminal.
2.4. Preparando o ambiente para
desenvolvimento em Windows
Em sistemas Windows, o Python, por padrão, nãovem instalado.
Portanto, precisamos fazer a instalação. Como neste livro iremos
util izar a IDE Spyder, é fortemente recomendada a instalação do
pacote Python(x,y), que já vem com vários recursos para
programação em Python, inclusive com o próprio ambiente Python
e a IDE Spyder.
Para fazer o download do Python(x,y), basta acessar a página do
projeto http://python-xy.github.io, salvar o arquivo e executar o
instalador. Siga o fluxo padrão de instalação em ambiente
Windows, não sendo necessário selecionar qualquer opção
adicional. Dessa forma, teremos suporte a muitas bibliotecas de
que porventura possamos precisar durante o desenvolvimento dos
nossos códigos.
2.5. Biblioteca zabbix-api
Nesta seção, veremos como é simples realizar a instalação da
biblioteca zabbix-api em ambientes Linux e Windows.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
2.5.1. Ambiente Linux
Utilizamos o PIP, um gerenciador alternativo para instalação de
pacotes Python. Executamos o seguinte comando para instalar o
PIP:
# apt- get ins t all p y t hon- pip -y
Com o PIP instalado, podemos executar o comando a seguir para
instalar a biblioteca zabbix-api:
# pip i n stall zabbix-api
Dessa forma, nosso ambiente estará pronto para iniciarmos o
desenvolvimento dos nossos códigos.
2.5.2. Ambiente Windows
Devemos baixar o scripf zabbix_api.py através do link
https://raw.githubusercontent.com/gescheit/scripts/master/zabbix
/zabbix_api.py e salvar o arquivo dentro do seguinte diretório:
C: \Byt hon27\Li b
Dessa forma, não precisaremos configurar nenhuma variável de
ambiente. Quando iniciarmos a IDE Spyder, automaticamente a
biblioteca zabbix-api será carregada para utilização, quando for
importada.
Obs.: se você instalou o pacote Python(x,y), ele já
vem com a ferramenta PIP. Prefira instalar qualquer
pacote Python através dessa ferramenta. A sintaxe
de comando segue o mesmo padrão demonstrado no
tópico 2.5.1.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
3
Primeiros Passos
Antes de entrarmos em detalhes nas classes e nos métodos da
API do Zabbix, veremos alguns exemplos básicos para você
compreender como funciona a estrutura padrão da biblioteca
zabbix-api. Assim, você irá se familiarizando com a forma de
montar as requisições no formato JSON e de incluí-las nos códigos.
3.1. Criando usuário para acessar a API
Apesar de não ser obrigatório, é importante criarmos um usuário
para acesso à API do Zabbix. O ideal em ambientes de produção é
que esse usuário nem tenha acesso ao frontend do Zabbix. Isso é
possível criando um usuário e o associando ao grupo No access to
the frontend. Assegure-se de que este usuário terá acesso total
para leitura e/ou gravação, caso for automatizar o processo de
criação de objetos (hosts, itens etc.). Para os casos de utilizar a API
do Zabbix apenas para gerar relatórios, não há necessidade de o
usuário criado ter permissão de escrita.
3.2. Montando a estrutura padrão
O início de cada arquivo .py que formos criar para nossos
projetos deverá ter a seguinte estrutura:
# -*- coding: u t f-8 - *-
from zabbix_api import ZabbixAPI
zapi = ZabbixAPI{server="http: //<ip- o u - hostname>
/zabbix")
zapi.login("<user>", "<password>" )
Obs.: você pode formatar a estrutura da forma como
lhe convir, não precisa seguir esse padrão.
Podemos observar que precisamos alterar três valores nessa
estrutura:
1. IP ou hostname do servidor Zabbix (caso você utilize o Zabbix na
raiz do seu servidor ou faça o uso de VirtualHost no Apache,
pode omitir o /zabbix).
2. Usuário que terá acesso à API.
3. Senha do usuário.
A vantagem de utilizarmos uma biblioteca, como no caso da
zabbix-api, é que alguns métodos já estão implementados, como,
por exemplo, user.login. Por esse motivo, esta obra não entrará
em detalhes da classe User. Para você saber mais detalhes sobre
essa classe, acesse https://www.zabbix.com/documentation
/2.4/manual/api/reference/user. Caso você escolha outra biblioteca
para trabalhar com a API do Zabbix, talvez seja preciso
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
implementar os métodos dessa classe em seu código. Utilizando a
API com Shell Script, essa implementação se faz necessária.
Ainda sobre a nossa estrutura inicial, temos a primeira linha, onde
informamos qual codificação iremos usar em nosso código.
Para os leitores que irão executar os códigos diretamente no
terminal do Linux, sugiro colocar o seguinte conteúdo no início da
estrutura:
#!/usr/bin/ env python
Essa linha será importante para quando formos executar os
scripts sem precisar executar o código passando o interpretador.
Em vez de executarmos o código assim:
# p y t hon codigo . p y
Poderemos executar da seguinte forma:
# . / c o d i g o .py
Lembrando que isso não é obrigatório, mas é importante para
evitar interpretações erradas durante a execução do código.
3.3. Obtendo IDs e nomes dos hosts
Veremos agora um exemplo simples, onde iremos utilizar o
método host.get para recuperar os IDs e nomes de todos os hosts
configurados. Antes, vamos observar o seguinte trecho do código,
que é a requisição no formato JSON:
{
" j sonrpc" : "2.0",
"met hod": "host . get" ,
"params": {
"output" : [
"hos t id",
" hos t"
Utilizando a biblioteca Python zabbix-api , essa requisição ficará
com o seguinte formato:
h osts = zapi .host . get ({
" output": [
]
} )
" host id",
"host"
print hos t s
O resultado da requisição é o seguinte:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
[ {u' host': u'Zabbix server', u 'hostid ' :
u 'l0084'}, {u'host' : u'Cliente', u' hostid':
u 'l0107'}, {u'host': u'Cable Modem', u' host id':
u 'l0106r}, {u'host' : u'Test e J anssen', u 'hostid':
u 'l0109'}, {u'host': u'nmap', u' hostid':
u ' 10142' } J
É uma saída no formato JSON, certo?
Porém, se pretendêssemos fazer um sistema, ficaria mais fácil se
o resultado viesse apenas com os valores dos dados requisitados.
É preciso usar algum conversor para isso? A resposta é não. O
conteúdo da saída no formato JSON é armazenado em uma
estrutura padronizada para troca de dados, formada por uma
coleção de pares nome/valor e por lista de valores. Pensando em
linguagens de programação, essa estrutura pode ser armazenada
em listas, vetores, matrizes etc. Podemos observar na figura a
seguir como essa estrutura é armazenada em Python:
,.
lndex Type Size Value
{u 'host ' : u' Zabbix server', u' hostid ' : u 'leil84 '}
r-····--·········i
!o : dict 2
t ........................ i
1 dict 2 {u 'host' : u'Cliente', u' hostid ': u'10107 ' }
2 dict 2 {u' host': u'Cable Modem' , u' hostid': u'10106' }
3 dict 2 {u 'host': u 'TesteJanssen ' , u'hostid': u'10109' }
4 dict 2 {u 'host' : u'nmap', u'hostid' : u '10142'}
Temos aqui um objeto no qual foram armazenados apenas os
campos solicitados na requisição, ou seja, nome do host e ID.
Cada item na lista é identificado por um índice (que neste caso é do
tipo dicionário). Portanto, basta acessarmos os índices de cada
item do objeto e imprimir os valores correspondentes. O código a
seguir faz o que pretendemos:
hosts = zapi.host.get({
} )
"out put 11 : [
"hostid11 ,
"host"
for x in h o s t s:
print x [ " hostid11 J , "- ", x [ " host 11 J
Observe que incluímos uma estrutura de repetição em nosso
código, pois a variável hosts está armazenando uma lista e o
interpretador do Python já sabe qual é a quantidade de elementos
que temos na lista.
Podemos traduzir a instrução da seguinte maneira:
);;>- Para cada índice encontrado na lista hosts, imprima 10 e
nome do host.
Observe também que o x representa o índice da nossa lista.
Vamos utilizar outro método. Agora não utilizaremos o for, pois não
queremos imprimir todos os elementos da lista. Queremos saber
qual é o nome do host que está na posição 1 no conjunto de
índices. Para isso utilizamos o códigoa seguir:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
hosts = zapi.host.get({
"out put": [
"hos t id" ,
"host"
} )
p rint hosts [1 ] ["host"]
Ou:
hos t s = zapi.host.get({
"output": [
"hostid",
"host"
} ) [1] [ "hos t" ]
p rint hosts
A saída das duas execuções anteriores será a mesma, ou seja:
Cliente
Esses dois últimos exemplos foram apenas para demonstrar que
conseguimos acessar diretamente um índice na lista, não
necessitando utilizar uma estrutura de controle para percorrer todos
os itens de uma lista. Também é possível a impressão das chaves
presentes na lista do tipo dicionário executando comandos
diretamente do console do Python. Por exemplo: após a execução
do código anterior, digite o seguinte comando:
hosts [1]. keys ()
A saída do comando é:
[u'host', u' hos t id']
Exatamente os dois campos que solicitamos no output da
requisição. A figura a seguir exibe o valor dos campos, referente ao
índice 1 na lista:
Type Size Value .. -................. ..
' '
j host r unicode 1
l ................... .J
Cliente
hostid unicode 1 16107
Para encerrar este capítulo, nosso código final para obter a lista
de todos os hosts cadastrados no servidor Zabbix, imprimindo o
nome de cada hoste seu respectivo 10:
#!/usr/bin/e nv python
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
# - *- coding: utf-8 -*-
from zabbix_api import ZabbixAPI
zapi = ZabbixAPI (server="http : //192 . 168 .0.112
/zabbix" )
zapi.login("apiuser", "apipasswd")
hosts = zapi.host.get{{
} )
"output": I
"hostid",
"host"
for x in hosts:
print x {"hostid"J, "- ", x["host" ]
E a saída após execução do código:
10106 - Cable Modem
10109 - TesteJanssen
10084 - Zabbix server
10107 - Cliente
10110 - Nmap
3.4. Organizando os dados
O leitor deve ter percebido que o exemplo anterior não está
ordenando os registros, nem com o 10 , nem com o nome do host.
Vamos adicionar um novo parâmetro à nossa requisição. O
sortfield classifica o resultado de acordo com as propriedades
passadas. Vejamos a seguir como fica o código incluindo esse
parâmetro:
#!/usr/bin/env python
# -*- coding: utf- 8 - * -
from zabbix_api import ZabbixAPI
zapi = ZabbixAPI{server="http://192.168. 0 .112
/zabbix")
zapi.login("apiuser", "apipasswd")
hosts = zapi.host.get ({
} )
"output": [
"hostid",
"host"
l ,
"sortfield": "name"
for x in hosts :
print x["hostid" J , "- ", x{"host"J
Observe a saída após a execução do código:
10106 - Cable Modem
10107 - Cliente
10142 - nmap
10109 - TesteJanssen
10084 - Zabbix server
Agora está ordenado corretamente.
Para uma ordenação inversa, ou seja, na forma decrescente,
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
basta incluirmos outro parâmetro na nossa requisição. Desta vez,
incluiremos o parâmetro sortorder. Vejamos a seguir apenas o
trecho onde ocorre a mudança:
hosts = zapi.host.get ({
"output": [
} )
"hostid",
"host"
l ,
"sortfield": "name",
"sortorder": "DESC"
for x in hosts:
print x ["hostid "J, "- ", x["host" J
O resultado da consulta:
1 0 084 - Zabbix server
1 010 9 - TesteJanssen
1 0142 - nmap
1010 7 - Cliente
1010 6 - Cable Modem
Podemos observar que o parâmetro sortfield foi referenciado
com o valor name. As propriedades dos métodos da API têm
padrões definidos. Não podemos passar qualquer valor nessas
propriedades. Por exemplo, o parâmetro sortfield apenas aceita os
valores: hostid, host, name e status. Veremos detalhes sobre os
parâmetros dos métodos no Capítulo 5.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
4
Referências e
Notações
Nesta seção, veremos com quais tipos de dados a API do Zabbix
trabalha e também os parâmetros comuns do método get.
Cada método da API possui objetos que podem ser retornados
através de suas propriedades. Essas propriedades possuem tipos
de dados que devem ser respeitados para que a requisição dos
dados retorne o pedido com sucesso.
A API do Zabbix suporta os seguintes tipos de dados:
Tipo Descrição
Bool Um valor booleano, ou seja, verdadeiro ou falso.
Flag O valor é considerado verdadeiro se ele é passado
e não nulo. Caso contrário, falso.
lnteger Número inteiro.
Float Número de ponto flutuante.
String Uma sequência de texto.
Text Uma sequência de texto mais longo.
Timestamp Unix timestamp.
Array Sequência ordenada de valores. Uma matriz
simples.
Object Uma matriz associativa.
Query Conjunto de nomes apropriados para retornar
apenas propriedades específicas.
4.1. Etiquetas de propriedades
Algumas propriedades dos objetos são marcadas com etiquetas
curtas para descrever seu comportamento. Os seguintes rótulos
são usados:
)> Readonly. O valor da propriedade é estabelecido
automaticamente e não pode ser definido ou alterado pelo
cliente.
)> Constant. O valor da propriedade pode ser definido durante a
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
criação de um objeto, mas não pode ser alterado
posteriormente.
Na tabela a seguir, podemos ver um exemplo de etiqueta de
propriedade.
Propriedade Tipo Descrição
Hostid string (readonly) ID do host.
eventsource integer (constant) Tipo de evento que a ação irá
controlar.
A etiqueta da primeira linha no exemplo anterior indica que a
propriedade Hostid não pode ter o seu valor alterado. Portanto, só
pode ser utilizada para uma consulta.
Essas etiquetas são encontradas na documentação oficial da API
do Zabbix, na listagem das propriedades das classes da API.
4.2. Objetos
Cada classe da API do Zabbix possui uma referência de seus
objetos, cada um possuindo propriedades e seus tipos de dados.
Essas propriedades são exibidas em formato de tabela contendo:
)> Nome da propriedade
)> Tipo
)> Descrição
Como a listagem das propriedades dos objetos é muito extensa,
a cada classe apresentada nesta obra indicaremos o link para
acesso à documentação oficial referente ao objeto da classe.
4.3. Parâmetros comuns do método
"get"
Na maioria das vezes, ao desenvolvermos nossos códigos para
consumir os dados disponibilizados via API do Zabbix, utilizaremos
os métodos get de cada classe da API do Zabbix. Esse método
possui vários parâmetros em comum. Descreveremos a seguir os
parâmetros que são suportados por todos os métodos get:
Parâmetro Tipo
countOutput Flag
Editable Boolean
excludeSearch Flag
Filter Object
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Descrição
Retorna o
registros
número de
encontrados
resultado no
pesquisado.
Se definido como
verdadeiro, retorna
apenas os objetos em
que o usuário tenha
permissão de escrita.
Padrão: false.
Retorna resultados que
não correspondem aos
critérios mencionados
no parâmetro de
search.
Retorna apenas os
resultados que
correspondem
exatamente ao filtro
passado.
Aceita uma matriz,
onde as chaves são
nomes de propriedade
e os valores são um
valor único ou uma
matriz de valores que
possam combinar com
os registros buscados.
Não funciona para
campos de texto.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
5
Classes e Métodos da
API
Cada classe possui uma lista com os seus objetos e suas
propriedades correspondentes. Essas propriedades estão
relacionadas aos campos presentes nas telas da interface web
referentes a cada objeto.
Este capítulo apresentará alguns métodos de classes da API que
eu julgo serem as mais importantes para quem está aprendendo a
utilizar a API do Zabbix. Em cada classe, apresentarei algumas
características, métodos, parâmetros aceitos e valores retornados,
além de exemplos com métodos das classes.
Vale ressaltar que alguns métodos aceitam parâmetros adicionais
em suas requisições feitas à API do Zabbix. Nesta obra não irei
entrar em detalhes sobre todos os parâmetros e propriedades dos
métodos das classes, por ser um materialbem amplo e disponível
na documentação oficial. Não faria muito sentido eu transportar um
conteúdo existente apenas para dar volume a esta obra. Porém,
para não deixar o leitor às cegas, informarei as referências dos
objetos e do método de cada exemplo que for abordado.
Todos os exemplos mostrados neste capítulo utilizarão a
estrutura já exibida anteriormente. Opcionalmente, você pode
adicionar o parâmetro log_level para exibir a saída da execução do
código e também para identificar os resultados das requisições
(falaremos mais sobre log_level no Capítulo 11 ). Então, para não
ficar repetindo muito código desnecessariamente, mostraremos a
seguir a estrutura inicial que usaremos em cada exemplo presente
neste capítulo. A estrutura é a seguinte:
#! / usr / bin/ e nv python
# -*- coding: u t f-8 - *-
from zabbix_api import ZabbixAPI
zapi = ZabbixAPI {server="http: / /<ip-ou -
fqd n>/ zab bix" )
zapi. l ogirr ( "<user>", "<password>")
A seguir, começaremos os estudos das classes e seus métodos
mais comumente utilizados.
5.1. API lnfo
Esta classe foi projetada para recuperar informação sobre a API.
5.1.1. Referências do objeto
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Esta classe não tem objetos disponíveis.
5.1.2. Métodos disponíveis
)> apiinfo.version
5.1.2.1. apiinfo. version
Recupera a versão da API utilizada.
Parâmetros aceitos
O método aceita um array vazio.
Obs.: este método está disponível para usuários não
autenticados e deve ser chamado sem o parâmetro
auth na requisição JSON-RPC. Como estamos
utilizando uma biblioteca, não precisamos nos
preocupar com esse detalhe, pois a biblioteca utiliza
uma função interna.
Valores retornados
Retorna uma string com versão da API do Zabbix.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/apiinfo/version
Exemplo
Para consultarmos a versão presente da API do Zabbix em nosso
sistema, utilizamos o código a seguir:
versao = zapi .api_version()
print " Versão da API: " , v e r sao
Lembre-se de que precisamos usar a nossa estrutura padrão
para rodar o código. O resultado da execução desse código será:
Versã o da API : 2. 4 . 6
Observe o seguinte detalhe: nós atribuímos a chamada de uma
função à variável versao. A função api_version, presente na
biblioteca zabbix-api, é uma implementação do método
apiinfo.version. Não podemos confundir esses detalhes. Por isso,
recomendo sempre analisar o código da biblioteca para saber o que
pode ser feito com ela.
A seguir, temos o trecho do código que implementa esse método
na biblioteca zabbix-api:
def a p i_v ersion (self , **options ):
sel f. che ckauth ()
obj =
se l f. do_request (sel f.json_ obj ( 'API I nfo.versi on',
opti ons, auth=False ))
ret u rn obj['result']
Observe que o parâmetro auth recebe o valor False, pois,
conforme informado anteriormente, seu uso não é obrigatório para
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
consultar a versão da API do Zabbix. Outro detalhe a observar é o
método APllnfo.version (isso mesmo, a biblioteca vem com alguns
caracteres em caixa alta). Já peguei alguns problemas com alunos
do meu curso - ao utilizarem a biblioteca em ambiente Windows,
recebiam erro na execução do código. Se for o seu caso, altere
esse método para apiinfo.version (todo em caixa baixa).
5.2. Host
Esta classe foi projetada para trabalhar com hosts. Utilizada para
gerenciamento de hosts no que tange à criação, atualização de
dados e status, associação de grupos e templates.
5.2.1. Referência do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/host/object
5.2.2. Métodos disponíveis
)> host.create - Criar hosts.
)> host.delete - Excluir hosts.
)> host.get - Recuperar informações de hosts.
)> host.isreadable - Verificar se é possível ler informações.
)> host.iswritable - Verificar se é possível gravar informações.
)> host.massadd - Acrescentar informações de objetos
relacionados em massa.
)> host.massremove - Remover informações de objetos
relacionados em massa.
)> host.massupdate - Substituir ou remover objetos
relacionados a partir de hosts.
)> host.update - Atualizar hosts.
5.2.2.1. host.create
Este método permite criar novos hosts.
Parâmetros aceitos
Os parâmetros a seguir são obrigatórios para a criação de um
host:
)> host (nome)
)> groups
)> interfaces
A explicação para os parâmetros obrigatórios é simples. Para um
host ser criado, temos que dar a ele um nome, associá-lo a um
grupo de host e também adicionarmos uma interface com a qual a
comunicação do host será realizada. Esses parâmetros são do tipo
object/array, o que significa que podemos inserir um ou mais hosts
e associar um ou mais grupos e interfaces ao host criado em uma
única chamada ao método.
A lista completa com os parâmetros e propriedades aceitos para
a criação do host pode ser encontrada nos links contidos nas
referências do método e do objeto.
Valores retornados
Retorna um objeto que contém os IDs dos hosts criados sob a
propriedade hostids. A ordem dos IDs retornados corresponde à
ordem dos hosts passados.
Vale ressaltar que, ao usarmos a biblioteca zabbix-api, o 10 do
host criado não será exibido, a não ser se habilitarmos o Jog de
execução (entraremos em detalhe no Capítulo 11) ou
programarmos a exibição do host criado.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/host/create
Exemplo
Vamos criar um host chamado "Curso API" com uma interface IP.
Adicionaremos o host ao grupo Linux servers, cujo ID do grupo é
2, e iremos associar ao template Template OS Linux, cujo ID é
10001 . Também deixaremos o host com o status desabilitado, pois
por padrão ele fica habilitado para o monitoramento. A seguir o
código que cria o nosso host
zapi.host. create ({
"host": "Cu rsoAPI",
"status" : 1,
"interfaces": [
}
"type": 1,
""main": 1,
"usei p ": 1 ,
"ip ": "192.168. 0 .5",
"dns": "",
"port": 10050
l ,
"groups": [
"groupid": 2
}
l ,
"templates":
{
"templateid": 10001
} )
Nosso host criado já aparece na interface web, conforme
mostrado na figura a seguir:
.w;;;;-~ n-- -------
~ ......... :• .. ,. Z...•· ..,,, ..--10 ' l:"• •. "'°"
Lembra que eu comentei que o valor retornado ao criarmos um
host é o ID? Se você observar, o nosso código não fez esse
tratamento, ou seja, não ficou explícito que o ID do host seria
retornado. O 1 D do host só retorna quando consumimos a API
diretamente com ferramentas como curl ou wget. Como estamos
usando uma biblioteca, precisamos ativar o Jog ou codificar essa
saída. Sobre o Jog, veremos no Capítulo 11 ; já a codificação para
mostrarmos o 1 D do host criado é exibida conforme o exemplo a
seguir:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
hostcriado = zapi.host.create({
" host": "CursoAPIRemover",
"status": 1,
"interfaces":
.......
"type": 1,
"main": 1,
"useip ": 1,
"ip ": "192.168. 0 .5",
"'dns" : "",
"port": 10050
F=='':&roups" ·
' AvaibWitv •
. ia-
"group id" : 2
• Ili
'"'" 1 l!a l /
e " t emplates":
"templateid" : 10001
} )
p rint "ID d o host criado: ",
hostcriado ["hostids" ] [O ]
Observe que agora estamos armazenando a execução do
método host.create em uma variável, que chamei de hostcriado.
Em seguida, imprimimos a saída do ID do host criado. Veja que
interessante: o que foi armazenado na variável é uma estrutura de
dados do tipo dicionário, conforme podemos visualizar na seguinte
imagem:
Size Value
hostcriado dict 1 {u'hostids': [u'10160' J}
O ID do host criado é armazenado na propriedade hostids, que é
uma estrutura de dados do tipo lista, pois podemos criar mais de
um host na mesma chamada do método. A imagem a seguir mostra
o conteúdo da lista:
Key Type Síze Value
rh~id~--, fist1
L ..................... J
[u' 10160' J
ID do host criado armazenado em uma lista .
Na lista que foi criada, a chave para acessar o valor de cada item
é hostids, o mesmo nome da propriedade. Como neste caso
criamos um único host, nosso índice a ser acessado é o O (zero),
conforme podemos visualizar na imagem a seguir:
,
Index Type Size Value
r····-···---···1
!O i unicode 1
l .................. !
10160
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Acesso ao índice que armazena o ID do host criado.
Portanto, está explicado por que foi pedido para imprimir a
variável hostcriado seguido de ["hostids"](O], pois hostcriado é
um dicionário que contém a lista hostids e o índice O, que
armazena o valor que queremos imprimir.
O resultado da saída é impresso da seguinte maneira:
ID do host criado: 10160
Se imprimirmos apenas a variável hostcriado, a saída seria a
seguinte:
ID do host criado: {u'hostids': [u'10160 ']}
Nada convencional para os nossos propósitos. No item 8.2
mostrarei um exemplo para criarmos hosts automaticamente.
5.2.2.2. host.massadd
Este método permite adicionar simultaneamente vários objetos
relacionados a todos os hosts indicados.
Parâmetros aceitos
Parâmetros que contêm os IDs dos hosts para atualizar e os
objetos para adicionar a todos os hosts.
Os seguintes parâmetros são aceitos:
)> hosts (obrigatório)
)> groups
)> interfaces
)> macros
)> templates
Valores retornados
Retorna um objeto que contém os IDs dos hosts criados sob a
propriedade hostids.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/host/massadd
Exemplo
Precisamos associar um tem pi ate a dois hosts. Os 1 Os dos hosts
são 10159 e 10160, e o template que adicionaremos aos hosts tem
o ID 10131. A seguir, temos o código que adiciona o template aos
dois hosts:
zapi.h ost.massadd( {
"hosts": [
"hostid": 10159
} I
"hostid": 10160
] I
"templates":
{
"templateid": 1 0131
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
Os IDs deste exemplo são os hosts que cadastramos no tópico
5.2.2.1. Já o ID 10131 refere-se a um template que já estava
cadastrado, mas não foi referenciado em nenhum exemplo até o
momento. Iremos trabalhar com o template 10131 no tópico 5.4.2.1.
A imagem a seguir mostra a associação deste template aos hosts:
-·--·~-.,_.,_
5.2.2.3. host.isreadable
Este método verifica se os hosts consultados estão disponíveis
para leitura.
Parâmetros aceitos
IDs dos hosts a verificar.
Valores retornados
Retorna true se os hosts informados na consulta estiverem
disponíveis para leitura.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/hosUisreadable
Exemplo
Verificar se os hosts 10137 e 10138 estão disponíveis para
leitura. A seguir, temos o código que faz essa verificação:
lei tura = zapi. host.isreadable( [ ----..., . ...... _ , _ _,. , ""!'0 159,
" - Host(s) d isponíve i s para
l eitura, " Host(s) não d i sponíveis para
i:..- l!l::U:
l j;;l. tura" ..... 11 .
Repare na sintaxe do código. Aqui, não incluímos as "{}", pois se
trata apenas de uma lista (array) que devemos passar como
parâmetro, ao contrário dos exemplos vistos anteriormente, onde
passamos objetos. Neste exemplo, o retorno também é diferente,
pois estamos fazendo uma verificação. Portanto, o retorno será
exibido como true ou false. No exemplo, a variável leitura
armazena esse valor, conforme é exibido na imagem a seguir:
N:me Type Size V•lue
leitura bool l i i-ue
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
Os IDs deste exemplo são os hosts que cadastramos no tópico
5.2.2.1. Já o ID 10131 refere-se a um template que já estava
cadastrado, mas não foi referenciado em nenhum exemplo até o
momento. Iremos trabalhar com o template 10131 no tópico 5.4.2.1.
A imagem a seguir mostra a associação deste template aos hosts:
-·--·~-.,_.,_
5.2.2.3. host.isreadable
Este método verifica se os hosts consultados estão disponíveis
para leitura.
Parâmetros aceitos
IDs dos hosts a verificar.
Valores retornados
Retorna true se os hosts informados na consulta estiverem
disponíveis para leitura.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/hosUisreadable
Exemplo
Verificar se os hosts 10137 e 10138 estão disponíveis para
leitura. A seguir, temos o código que faz essa verificação:
lei tura = zapi. host.isreadable( [ ----..., ....... _ , _ _,. , ""!'0 159,
" - Host(s) d isponíve i s para
l eitura, " Host(s) não d i sponíveis para
i:..- l!l::U:
l j;;l. tura" ..... 11 .
Repare na sintaxe do código. Aqui, não incluímos as "{}", pois se
trata apenas de uma lista (array) que devemos passar como
parâmetro, ao contrário dos exemplos vistos anteriormente, onde
passamos objetos. Neste exemplo, o retorno também é diferente,
pois estamos fazendo uma verificação. Portanto, o retorno será
exibido como true ou false. No exemplo, a variável leitura
armazena esse valor, conforme é exibido na imagem a seguir:
N:me Type Size V•lue
leitura bool l i i-ue
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Neste exemplo, é importante frisar que essa verificação é
realizada de acordo com as permissões que um grupo de usuário
possui sobre os hosts. Portanto, se você estiver executando a
consulta como usuário Zabbix Super Admin, o resultado das
consultas sempre será true.
Esses exemplos dão base para utilizarmos os demais métodos
da classe Host. Como foram demonstrados exemplos do método
host.get no item 3.3, não há necessidade de repetirmos os
exemplos básicos. Exemplos avançados serão demonstrados no
Capítulo 8.
5.3. Host Group
Esta classe foi projetada para trabalhar com grupos de hosts.
Utilizada para gerenciamento de grupos de hosts, no que tange à
criação e atualização de dados.
5.3.1. Referências do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/hostgroup/object
5.3.2. Métodos disponíveis
)> hostgroup.create - Criar grupos de hosts.
)> hostgroup.delete - Excluir grupos de hosts.
)> hostgroup.get - Recuperar informações de grupos de hosts.
)> hostgroup.isreadable - Verificar se é possível ler
informações.
)> hostgroup.iswritable - Verificar se é possível gravar
informações.
)> hostgroup.massadd - Acrescentar informações de objetos
relacionados em massa.
)> hostgroup.massremove - Remover informações de objetos
relacionados em massa.
)> hostgroup.massupdate - Substituir ou remover objetos
relacionados a partir de grupos de hosts.
)> hostgroup.update -Atualizar grupos de hosts.
Os métodos da classe hostgroup são semelhantes aos métodos
da classe host. Com isso, mostraremos dois exemplos diferentes
dos demonstrados na classe host.
5.3.2.1. hostgroup.delete
Este método permite excluir grupos de hosts.
Obs.: um grupo não pode ser apagado se:
- contém hosts que pertencem apenas a este grupo;
- o grupo é marcado como interno.
O grupo de hosts marcado como interno é definido no menu
Administration > General > Others. Por padrão, esse valor é
Discovered hosts, conforme exibido na imagem a seguir:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
~~~~~~~~~~~~~~~~~~~~~~~~~~~-~N~~~-~-~~~&ido~)grupo~)deh~~parae~lui~ Valores retomados - que contém os IDs dos grupos de hosts
........ ~---J @
O..,.lwllll•-~ ~~ .... .
~ .... i.-~ ....... -·..- U...~·
\41-~-m,.. ,,.
-··
Quando um grupo de hosts é marcado como interno, o valor da
propriedade internai é 1. O padrão dessa propriedade ao criarmos
um grupo de host é O. Apenas um grupo pode ser marcado como
interno. Para comprovar que não podemos excluir um grupo de host
marcado como interno, observe na imagem a seguir que o botão
Delete encontra-se desabilitado:
---
......
Parâmetros aceitos
._._. ,o_,,,.....,,.
C,.,,.4"1oNL1
~us:-2 ,_... ........
Referência dométodo
https://www.zabbix.com/documentation/2.4/manual/api/reference
/hostgroup/delete
Exemplo
Como este método aceita apenas como parâmetro os IDs dos
grupos de hosts, basta apenas informarmos o(s) ID(s) dos grupos.
zapi.hostgroup. delete([
..... , .. ,._. , .,,.,. ...... ,~3
Observe que o formato do código teve uma pequena variação,
assim como vimos no método host.isreadable. Como estamos
passando um array de um único parâmetro, não precisamos
envolvê-lo entre chaves O. Essa característica deve ser assimilada
pelo leitor. Por isso, em cada método que estamos vendo nesta
obra, existe uma notação relacionada ao método em sua descrição.
5.3.2.2. hostgroup.massupdate
Este método permite substituir ou remover, simultaneamente,
objetos relacionados por vários grupos de hosts .
Parâmetros aceitos
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Parâmetros que contenham o 10 do grupo de hosts. Este método
aceita apenas os três parâmetros a seguir:
}> groups
}> hosts
}> templates
Valores retornados
Retorna um objeto que contém os IDs dos grupos de hosts
atualizados sob a propriedade groupids. A ordem dos IDs
retornados corresponde à ordem dos grupos de hosts passados.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/hostgroup/massupdate
Exemplo
Digamos que no grupo de hosts Web nós temos um host que
queremos substituir. Vamos substituir esse host por outros dois
hosts que não são membros do grupo Web. A seguir, o código da
solução:
zapi.hostgroup.ma ssupdat e( {
"groups": [
"groupid" : " 11"
l '
"hosts" :
"hostid " : "10148"
} '
{
" hostid": "10147"
} )
No exemplo, o groupid 11éo 10 do grupo Web. Passamos como
parâmetro hosts os IDs dos hosts que iremos incluir como membro
nesse grupo.
Obs.: não é possível atualizarmos um grupo de hosts
em massa caso o grupo contenha hosts que sejam
membros somente deste grupo. Por exemplo: os
hosts cujos IDs são 10151 e 10152 sejam membros
do grupo de ID 17. Se executarmos o código do
exemplo anterior substituindo 11 por 17, vai
aparecer uma mensagem de erro informando que um
dos objetos (no caso, os hosts) não pode ser deixado
sem um grupo. Essa é uma regra do Zabbix que
exige que um host seja membro de ao menos um
grupo de hosts. Portanto, você deve, antes de fazer
essa atualização, incluir os hosts como membros de
outro grupo. Essa observação também se aplica
quando existirem templates que são membros do
grupo de hosts.
5.4. Template
Esta classe foi projetada para trabalhar com templates. Utilizada
para gerenciamento de temp/ates , no que tange à criação,
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
atualização de dados e status, associação de grupos e templates.
5.4.1. Referências do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/template/object
5.4.2. Métodos disponíveis
)> template.create - Criar templates.
)> template.delete - Excluir templates.
)> template.get - Recuperar informações de templates.
)> template.isreadable - Verificar se é possível ler informações.
)> template.iswritable - Verificar se é possível gravar
informações.
)> template.massadd - Acrescentar informações de objetos
relacionados em massa.
)> template.massremove - Remover informações de objetos
relacionados em massa.
)> template.massupdate - Substituir ou remover objetos
relacionados a partir de templates.
)> template.update -Atualizar templates.
Os métodos da classe template são semelhantes aos métodos
da classe host. Com isso, mostraremos dois exemplos diferentes
dos demonstrados na classe host.
5.4.2.1. template.update
Este método permite atualizar templates.
Parâmetros aceitos
Propriedades a serem atualizadas. A propriedade templateid
obrigatoriamente deve ser definida para cada template que deseja
atualizar. Todas as outras propriedades são opcionais. Apenas as
propriedades indicadas serão atualizadas, todas as demais
permanecerão inalteradas.
Valores retornados
Retorna um objeto que contém os IDs dos templates atualizados,
sob a propriedade templateids.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/template/update
Exemplo
Atualizar a descrição e o nome do template com ID 11. A seguir, o
código que atualiza a descrição do template:
zapi.template.update( {
"templateid" : "10111",
"name": "Temp late a ltera do 1",
"description": "Descrição para template
alterado 1"
} )
A imagem a seguir mostra os campos alterados:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
+- e lf in.168-2 1os , métodõs. A seguir, o código com exemplo para alterar dois
~~~~~~-'---'="~~~~~~~~,,,~=~=~===~=~=:.__=~=~=~=~=~=~=-=_=_=_=_=_=_=_,,...--rempfa~es simultaneamente:
f • ....,.,. t . .. , .. , .... T ._..,_ -------------------------------'
T.._,__ -~l.-
111 ..... _..,. 1'~• ..WW. I 1 ........ _
·..-.t..t ..
--
...__
._ ...
o ......... ...
~ .... , .. ·-..._._._ --·-1•Jh ....... mw .. ~, ....
ou-.1 .... · e.....ut
c_,,..._,-~
c-AJt~:
Td.C-
W•-
Podemos visualizar em destaque na imagem os valores dos
campos alterados. Observe que atualizamos a propriedade name,
que na interface web do Zabbix é representada por Visible name.
Caso seja necessano alterar o campo Template name, a
propriedade do método é host (que é como o Zabbix trata um
template).
Detalhe é que esse método permite a atualização de mais de um
template na mesma execução do código. O que o diferencia do
método template.massupdate é que o massupdate faz a
atualização em massa de objetos relacionados e o update somente
atualiza as propriedades. Essa diferenciação vale para os demais
z a p i. templ ate . update( [
" t emplateid" : " 1 011 1",
"name ": "Te mplat e alterado 1",
"des cri pti on": "Descrição p ara t e mpl ate
alt e r a do 1 novamente "
} ,
" t emplateid": " 1 0131",
"na me ": " Template alterado 2",
"descri pti on": "Descrição p ara t e mpl ate
alt e r a do 2 novame nte"
l )
Observe que, para atualizar mais de um registro, precisamos
informá-los entre colchetes e separados por vírgula, para identificá-
los dentro de um array.
5.4.2.2. template.massremove
Este método permite remover objetos relacionados por vários
tem pi ates.
Parâmetros aceitos
Parâmetros que contêm os IDs dos templates para atualizar e os
objetos que devem ser removidos.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Valores retornados
Retorna um objeto que contém os IDs dos grupos dos templates
atualizados sob a propriedade templateids. A ordem dos IDs
retornados corresponde à ordem dos templates passados.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/template/massremove
Exemplo
Vamos desassociar dois templates associados a um mesmo
grupo de hosts. A seguir, o código que remove essa associação:
zapi.template .massremove({
"templat eid s":
"10111",
"10131"
l ,
"groupids": "5"
} )
A observação do método hostgroup.massupdate também se
aplica neste exemplo, pois não podemos remover um template e
deixá-lo sem associação a um grupo de hosts. Se você tentar
remover um template que não esteja associado a outro grupo (por
exemplo, o grupo Templates), a API retornará a mensagem de erro
a seguir:
ZabbixAPIException: (u'Error - 3260 2 : I nvalid
params., One of the objects is lef t without a
host group. while sending {"params":
{"groupids": "5", "templateids": ["10111",
"10131"] } , "j sonrp c " : "2 . O", "method" :
"template.ma ssremove", "auth":
"b7dcf87a c4c51932a510f48430b0 7069", "id" : 1 }',
- 32602)
Observe a imagem a seguir, que mostra os templates que serão
desassociados:
-·
-
--
~ ·' •;;e--=------
-"
~ 2.1 c:wwnn m• '»='d ~ ... m:u.~ -n
"""'" ,.,.......
~<•
, ....... "'=' ., .... 'O"~•
,......,, ... ft !lr:!tee.•r!!t!lrtt""""t! .. 7 1ww1,,... nt mim Pd
~ . .._f sn """1n'e •er!e! m ""XI- ~.::1.!t!,..,. P' .........,, Tr=ei.o• t" trfr:, ~
*-U(M J?U.k:::â ,_,,,.,,rià,....AMC.~~
.,.,,, .. ,,_,,,..,, :a..u:.a-+r•g.,.. ~ • ..,. .. .,._ ...:e·+.••·,... __j
....... ! 1 ... ,..'«"'se! 1 ppftee. ... '*' ..... tt='·! t .,.,.. -·-t:.......::
Após a execução do código, o grupo Discovered hosts, cujo 10
é 5, não terá mais nenhum template associado, conforme podemos
visualizar na imagem a seguir:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
"""" '
E
- " ·-·
=lOl ~ .......... e,_, .. ,...,._..._,.,
'fc:d:aa 'º ~
"""' ~10'
' "Mr' rftt*I11
podem ser criados, excluídos ou
5.5.1. Referências do objeto ....
https://www.zabbix.com/documentation/2.4/manual/api/reference
/item/object
5.5.2. Métodos disponíveis
)> item.create - Criar itens.
)> item.delete - Excluir itens.
.,_ ...... ._..._~;::~ü:::.:~=~ )> item.get - Recuperar informações de itens.
:.,,~ ,~ =~~~~~~~~~E~~~~~~~~E~E§ã§:_1~~~~-~·~~j }> item.isreadable - Verificar se é possível ler informações. g -, ",.,.._, .. _. · -- · .t - .... . _ , ' · .,___};> item.iswritable-Verificar se é possível gravar informações.
~._Nã°lpodemos confundir remover com desassociar. Neste caso, )> item.update - Atualizar hosts.
remQ:i1er apagaria o cadastro do template nos registros do Zabbix. Veremos dois exemplos utilizando 0 método item.update. Os
Obs.: apesar de não ser prática da maioria dos
usuar1os, que agrupa seus templates somente no
grupo Template, é normal encontrarmos ambientes
cujos templates estão associados a grupos de hosts
separados, tomando a administração mais
organizada •
.....
5.5. Item
Esta classe foi projetada para trabalhar com itens. Utilizada para
gerenciamento de itens, no que tange à criação, atualização de
dados e status, além de associação com aplicações. Itens de
demais métodos seguem o mesmo padrão das classes já vistas até
aqui.
5.5.2.1. item.update
Este método permite atualizar itens existentes.
Parâmetros aceitos
Propriedades a serem atualizadas. A propriedade itemid
obrigatoriamente deve ser definida para cada item que se deseja
atualizar; todas as outras propriedades são opcionais. Apenas as
propriedades indicadas serão atualizadas e todas as demais
permanecerão inalteradas.
Valores retornados
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Retorna um objeto que contém os IDs dos itens atualizados, sob
a propriedade itemids.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/item/update
Exemplo
Desabilitar a coleta de dados de um item que está apresentando
erro no monitoramento. A seguir, o código que desabilita o item cujo
ID é 25746:
zapi. item. u pdat e ({
" ite mid": "25746",
"status": 1
} )
Agora vamos utilizar o mesmo método para fazer uma
atualização de status para mais de um item. Digamos que
identificamos problemas nos itens 257 45 e 257 46 e que fizemos
uma atualização na chave desses dois itens e agora podemos
habilitar a coleta de dados neles. Observe o código a seguir:
zapi. item. update ([
} '
"itemid": "25745",
"status": O
}
l )
"itemid" : "25746",
"status" : O
No exemplo, estamos habilitando os itens 25745 e 25746. No
momento em que estou escrevendo esta obra, não existe o método
item.massupdate. Portanto, para demonstrar como é possível
programar essa solução, eu fiz a chamada ao método item.update
passando uma lista dos itens que desejamos atualizar.
Logicamente, essa solução foi baseada em fazer uma única
requisição ao método. Uma alternativa é utilizar uma estrutura de
controle, verificar os itens que devem ser atualizados e fazer a
chamada para atualizar cada item percorrido nessa estrutura.
No Capítulo 8, mostrarei um exemplo de como fazer para
localizar os itens não suportados e desabilitá-los automaticamente.
5.6. Trigger
Esta classe foi projetada para trabalhar com triggers. Utilizada
para gerenciamento de triggers, no que tange à criação, atualização
de dados e status, além de inclusão e exclusão de dependências.
5.6.1. Referências do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/trigger/object
5.6.2. Métodos disponíveis
):>- trigger.adddependencies - Adicionar dependências de
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
triggers.
)> trigger.create - Criar triggers.
)> trigger.delete - Excluir triggers.
)> trigger.deletedependencies - Excluir dependências de
triggers.
)> trigger.get - Recuperar informações de triggers.
)> trigger.isreadable - Verificar se é possível ler informações.
)> trigger.iswritable - Verificar se é possível gravar
informações.
)> trigger.update -Atualizar triggers.
Veremos o método trigger.adddependencies. Os demais
métodos seguem o mesmo padrão das classes já vistas até aqui. O
método trigger.deletedependencies é bem básico, bastando
passarmos o 10 da(s) trigger(s) que queremos remover às
dependências. Basicamente, é parecido com qualquer método
delete das demais classes.
5.6.2.1. trigger.adddependencies
Este método permite adicionar dependências de triggers.
Parâmetros aceitos
Propriedades a serem atualizadas. Para este método, apenas
duas propriedades devem ser passadas: o 10 da trigger e o 10 da
trigger da qual ela é dependente.
Valores retornados
Retorna um objeto que contém os IOs das triggers dependentes,
sob a propriedade triggerids.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/trigger/adddependencies
Exemplo
Adicionar dependência da trigger 14410 para a trigger 14411 :
zapi. t rigger. a dd dependencies ( {
"trig gerid" : " 14410",
"depend sOnTri ggerid": "1 4 411"
} )
Veja na imagem a seguir como fica a tela de triggers com a
adição dessa dependência:
. ........ -
~-· •- flf .W&J"U 1l•'teMnd!wh= 1 • =-t•<ttQC!M!' li ~0)) ..
5.7. History
Esta classe foi projetada para recuperar dados históricos do
monitoramento. Os históricos são diferentes conforme o tipo do
item da informação a ser recuperada. Por exemplo: o valor
retornado pode ser float, integer etc. Isso deve ser observado
quando se for recuperar uma informação do histórico, pois se faz
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
necessário saber qual é o tipo de informação a ser recuperada. No
Capítulo 4 vimos os tipos de dados com que o Zabbix trabalha.
Vale ressaltar que os históricos são gerados pelo Zabbix Server e
não podem ser modificados via API.
5. 7 .1. Referências do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/history/object
5. 7 .2. Métodos disponíveis
~ history.get - Recuperar dados históricos.
~I1LJ . history.get
-5~] método permite recuperar dados históricos do
monitoramento de acordo com os parâmetros informados nas
~ções.
P'ãrâlftetros aceitos
-.i)í.bistory - Tipo de dado do histórico a ser retornado.
- h ostids - Retornar apenas dados históricos dos hosts
-~ jformados.
~ itemids - Retornar apenas dados históricos dos itens
informados.
~ time_from - Retornar apenas dados históricos recebidos
após o período informado.
~ time_till - Retornar apenas dados históricos recebidos antes
do período informado.
Além dos parâmetros do método, também são aceitos os
parâmetros comuns do método get, como mencionado no item 4.3.
Os parâmetros time_from e time_till são do tipo tímestamp.
Portanto, devem ser passados no formato específico. No tópico 7.3
veremos alguns exemplos com conversão de datas nesse formato.
Obs.: uma boa fonte para converter datas é o site
http://www.epochconverter.com. Muito simples e
fácil de usar, com exemplos práticos de uso em
várias linguagens de programação.
Valores retornados
Retorna um array com os valores dos históricos coletados. Caso
for utilizado o parâmetro countOutput, retorna a contagem dos
objetos da consulta.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference/history/get
Exemplo
Recuperar dados históricos do item 23668 em um determinado
período:
historico = zapi .history.get({
"itemid s":
23668
] ,
"history": O,
"output": " ext e nd",
"time from" : "1438387200",
"time t ill": "1439250959"
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
print historico
Neste exemplo, foi selecionado o período de 01/08/2015 00:00:00
GMT a 10/08/2015 23:55:59 GMT. Devemos tomar cuidado ao
trabalhar com dados nesse formato. O servidor deve estar ajustado
com o timezone correto para evitar retornos das consultas com
horários diferentes. O retorno desse exemplo trouxe 3. 783
registros. A seguir, temos um trecho do retorno:
[ {u' ite mid': u ' 23668', u' ns': u' 4560138',
u 'value':
u '39.6000', u'clock': u'1438642469' } ,
{u'i t emid': u'23668', u'ns': u '60 6322530 ',
u 'value': u'40.0000', u'clock': u '1438642498'},
{u' itemid': u' 23668', u' ns': u ' 359596042',
u ' value': u' 39. 4000', u' clock': u ' 1438642528' } ,
{u' itemid': u' 23668', u' ns': u ' 665785765',
u 'value': u'39.6000',
u 'clock': u'1438642558'}, {u'itemid': u'23668',
u ' ns': u' 879789824', u'value': u' 39. 9000 ',
u 'clock':
u ' 1438642588' } , {u' itemid': u' 23668', u' ns':
u '346500 481 ', u'value': u'39.8000 ', u'clock' :
u '1438642618 ' } , {u'itemid': u'23668', u'ns':
u '738119850 ', u'value': u'39.80 00 ',
u ' clock': u' 1438642648'}, {u' itemid': u' 23668',
u 'ns': u'33470392', u'val ue' : u'39.60 00',
u ' clock' : u' 1438642679'}, {u' itemid' : u' 23668',
u ' ns' : u ' 549818930 ', u' value' : u' 40. 0 000 ',
u' clock': u' 1438642708'}, {u ' itemid': u' 23668',
u'ns': u'235 125808', u 'value': u'39.5000',
u' clock' : u' 1 438642738'}, {u ' itemid': u' 23668',
u'ns': u' 374474688', u 'value': u' 39.8000',
u' clock' : u' 1 438642768'}, {u ' itemid ': u' 23668',
u'ns': u'684474290', u 'value': u '40 .0000',
u' clock': u' 1 438642798'},
Observe que o retorno não foi formatado. Veremos um exemplo
prático no Capítulo 7.
5.8. Event
Esta classe foi projetada para trabalhar com eventos. Eventos
são criados pelo Zabbix Server e não podem ser modificados via
API.
5.8.1. Referências do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/event/object
5.8.2. Métodos disponíveis
)> event.get - Recuperar eventos.
)> event.acknowledge - Reconhecer eventos.
5.8.2.1. event.get
Este método permite obter eventos de acordo com os parâmetros
informados nas requisições.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Parâmetros aceitos
Este método é muito utilizado para criarmos relatórios gerenciais.
A lista de parâmetros aceitos é extensa, e, por esse motivo, é
inviável transcrevê-la para esta obra. Você pode obter a lista
completa no link constado na referência do método, disponível a
seguir.
Valores retornados
Retorna um array com os valores dos eventos obtidos. Se for
utilizado o parâmetro countOutput, retorna a contagem dos objetos
obtidos na consulta.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/event/get
Exemplo
Recuperar eventos criados em um determinado período:
evencos = zapi . event .get({
"output": "extend",
} )
"time from": "1438387200",
"time till": "1439250959",
"sortfield":
l ,
"clock",
"eventid"
"sorcorder": "DESC"
pri nt eventos
Assim como no exemplo do método history.get, utilizamos o
mesmo período para o exemplo atual. Uma observação é que
utilizamos o parâmetro sortfield para organizar os dados por ordem
de clock e eventid. O retorno será parecido com o exemplo do
tópico 5. 7.2.1 , não tendo a saída formatada.
5.8.2.2. event.acknowledge
Este método permite reconhecer eventos e adicionar uma
mensagem de confirmação. Caso um acontecimento já tenha sido
reconhecido, uma nova mensagem ainda será adicionada ao
evento.
Parâmetros aceitos
)> eventids - IDs dos eventos a serem reconhecidos.
)> message - Texto da mensagem para o reconhecimento.
Valores retornados
Retorna um objeto que contém os IDs dos eventos reconhecidos
sob a propriedade eventids.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/event/acknowledge
Exemplo
'
O evento que aconteceu no sistema está listado conforme exibido
na imagem a seguir:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Host group
Curso API O
'tiost ~---------------[Tu1][g]'
Host group Without problems With problems Total
Curso A!>J 1
Host lssue Last change Age lnfo Ack Actions
1
1 of 1 issu• ls st>own
'Upcb.t..d: 14:08:S9
O 10 desse evento é 3264, conforme pode ser observado na
imagem a seguir:
......
......... _
m12 *" 'tl"" ,.~
Ciomm•n
lilo >!k~sf-.
.. _ ........
ow.taon •••
:.t4 •itr-
'"
Observe que é a mesma trigger exibida na imagem anterior, que
mostra uma parte do dashboard do Zabbix. Foi destacado o
eventid para mostrar o código do evento que iremos reconhecer,
além de exibir que o evento ainda se encontra sem
reconhecimento, conforme podemos ver no último painel inferior,
destacado por uma seta. Esta tela foi obtida clicando na data do
acontecimento do evento, na tela de dashboard. Depois, na tela de
eventos, novamente clicamos na data em que o evento ocorreu.
Executaremos o código a seguir para reconhecer o evento 3264:
zapi.event.acknowledge({
"eventids": "3264",
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
"message": "Evento do l ivro reconhecido."
} )
AP.é-
1
a execução do código, o evento já é exibido no dashboard
como ~econhec ido. Ao passarmos o cursor do mouse sobre o Yes,
su~ge.Lm pop-up com a mensagem cadastrada, o horário em que o
even~1 foi reconhecido e o usuário que fez o registro. Entre
""º parênt ses, é exibido o número de vezes em que foi cadastrada
uma rrlensagem para o evento. A imagem a seguir ilustra o evento
r._eeon~ecido:
êll
Host group OtSMttt Hlgh Avttage. wamlng lnformàtlon Hot das-.sifled
Ho.st oroup Without prob1~11 Wlth probl~s Tot1'1
o
1 ttdw' w ,, o
lnfo Ade A<tlons
, , .
5.9. Alert
Esta classe foi projetada para trabalhar com alertas. Os alertas
são gerados no Zabbix através das ações cadastradas no menu
Configuration > Actions. Esses alertas são gerados
automaticamente pelo Zabbix e não podem ser modificados via API.
Vale ressaltar que não devemos confundir o método action.get
com o alert.get. O primeiro é utilizado para obter as configurações
cadastradas para determinada ação. O segundo é utilizado para
obtermos os alertas que foram gerados conforme a condição
cadastrada nas ações.
5.9.1. Referências do objeto
https://www.zabbix.com/documentation/2.4/manual/api/reference
/alert
5.9.2. Métodos disponíveis
)i> alert.get - Recuperar alertas.
5.9.2.1. alert.get
Este método permite obter alertas de acordo com os parâmetros
informados nas requisições.
Parâmetros aceitos
-----------------
1 °' Tt1ue use• "'"''"""15 Este método é muito utilizado para criar relatórios gerenciais. A
~·""' l4i.lllljl!I
:01,_.1' 1' 1$•:0 ~m'" :Obbl• Admlol"'"'°') E- .... 0.1...,,.. ,..fºlrt"..t;i • t ºt ' · ' · · ' ij~~~~~~~~~~~~~~~~~~~-~~~~~~~~~~~~~~~na~u~ paramerosace1oseextensa, e, por esse motivo, e 1nv1avel
O evento reconhecido também pode ser visualizado na tela de
eventos: menu Monitoring > Events.
transcrevê-la para esta obra. Você pode obter a lista completa no
link constado na referência do método, disponível a seguir.
Valores retornados
Retorna um array com os objetos dos alertas ou a contagem dos
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
registros recuperados, caso o parâmetro countOutput seja usado.
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/alert/get
Exemplo
Verificar quantas vezes uma ação foi disparada em todo o
período de atividade do servidor Zabbix cuja mensagem tenha o
termossh.
alert a= zapi.alert.get({
"output": "extend",
"search": {
} )
"message": "ssh"
} ,
"actionid s": "7",
"countoutput ": "True",
print "Número de vezes que a ação foi disparada:
", a lerta
Observe que no exemplo foram adicionados dois parâmetros que
ainda não havíamos estudado até então: o search e o
countOutput. O search retorna os resultados que casam apenas
com o termo passado durante a consulta. Já o countOutput é bem
simples e tem um único propósito: retornar o número de registros
contados durante a requisição.
O resultado da execução do código é exibido a seguir:
Número de v.ezes que a ação foi d isparada : 19
Experimente executar o código retirando o parâmetro search ou
alterando o termo ssh por agente. Qual a quantidade de registros
que retornou?
5.1 O. lt Service
Esta classe foi projetada para trabalhar com serviços de TI.
Utilizada para gerenciamento de serviços de TI, no que tange à
criação e atualização de dados.
5.10.1. Referências do objeto
https:/lwww.zabbix.com/documentation/2.4/manual/api/reference
/service
5.10.2. Métodos disponíveis
);;>- service.adddependencies - Adicionar dependências entre
serviços de TI.
);;>- service.addtimes - Adicionar tempo de serviço.
);;>- service.create - Criar serviços de TI.
);;>- service.delete - Excluir serviços de TI.
);;>- service.deletedependencies - Excluir dependências entre
serviços de TI.
);;>- service.deletetimes - Excluir tempo de serviço.
);;>- service.get - Recuperar serviços de TI.
)>- service.getsla Recuperar informações sobre
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
disponibilidade de serviços de TI.
)> service.isreadable - Verificar se é possível ler informações.
)> service.iswritable - Verificar se é possível gravar
informações.
)> service.update - Atualizar serviço de TI.
5.10.2.1. service.getsla
Este método permite calcular as informações sobre a
disponibilidade de serviços de TI.
Parâmetros aceitos
)> serviceids - 1 Os dos serviços de TI.
)> intervals - Intervalo de tempo com os seguintes parâmetros
(em timestamp):
o from - Horário inicial do intervalo.
o to - Horário final do intervalo.
Valores retornados
Retorna as seguintes informações sobre a disponibilidade de
cada serviço de TI sob o ID de serviço correspondente:
)> status - Estado atual do serviço de TI.
)> problems - Triggers que atualmente estão em estado de
problema.
)> sla - Dados de SLA sobre cada período. Cada objeto
retornado possui as seguintes propriedades:
o from - Horário inicial do intervalo (timestamp).
o to - Horário final do intervalo (timestamp).
o sla - SLA do período determinado (f/oat).
o okTime - Período em que o serviço ficou em estado de
OK, em segundos (integer).
o problemTime - Período em que o serviço ficou em estado
de problema, em segundos (integer).
o downtimeTime - Período em que o serviço ficou em
inatividade programada, em segundos (integer).
Referência do método
https://www.zabbix.com/documentation/2.4/manual/api/reference
/service/getsla
Exemplo
Recuperar informações sobre a disponibilidade de um serviço
durante o período de 01/08/2015 a 31 /08/2015.
sla = zap i.service.getsla ( {
"serviceid s": "51 19" ,
"inte r vals" :
"from" : 1 438 3 87200 ,
"to ": 14410 655 99
print sla
O resultado da execução do código será:
{u' 5119': { u 'status': u'4', u ' p r oblems': [],
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
u ' s l a': [ {u' from': 1438387200, u' problemTime':
984014, u' t o' : 14410 65599, u'okTime': 1694385,
u 'downtimeTime': O, u 'sl a': 63.261112328671 )] } }
Isso porque nós não formatamos a saída. No Capítulo 7 será
demonstrado em detalhes como formataremos a saída das
requisições feitas à API. Alguns métodos mostrados neste capítulo
tiveram a saída formatada, porém de maneira simples. No Capítulo
7, veremos formatações um pouco mais trabalhadas, pois teremos
que acessar estruturas de dados como listas e dicionários, o que
torna a codificação mais custosa. Porém, uma vez que você esteja
familiarizado com a estrutura utilizada pelo formato JSON em
relação à linguagem de programação (no caso dos nossos
exemplos, Python), será fácil de aplicar a formatação da saída.
Conhecemos neste capítulo alguns métodos disponíveis na API
do Zabbix. Como expliquei no começo, a documentação da API do
Zabbix é bastante rica em detalhes, mostrando todos os métodos e
classes com que podemos trabalhar. Mostrei alguns exemplos
básicos, o que já lhe dá um norte de como a API do Zabbix deve
ser consumida. Nos próximos capítulos veremos outros exemplos
com mais detalhes de requisição e formatação de saída, além de
elevarmos um pouco o nível de codificação, mostrando como
automatizar tarefas, emitir relatórios etc.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
6
Ferramentas para
Formatação e
Validação de JSON
Como as requ1s1çoes e respostas são codificadas no formato
JSON, eu recomendo ao leitor utilizar algumas ferramentas que
servem para formatar e validar uma requisição. A formatação é
apenas para deixar o código mais legível. Observe o trecho de
código a seguir:
grupo_hosts = zapi.item.get( {"groupids":"4",
"filter" : {"key_":"agent.version"},
"output" : ["lastvalue", "hostid"J
} )
Podemos observar que a requisição JSON, escrita entre
parênteses, não está em um formato legível, como visto nos
exemplos dos capítulos anteriores. Digamos que esteja em um
formato compacto. Existem alguns sites que fazem a validação e
formatação do JSON que nós escrevemos. Eu recomendo que o
leitor use esse tipo de ferramenta para ir se acostumando com a
formatação mais legível (tabulada), que podemos visualizar a
seguir, usando o mesmo exemplo anterior:
gru po_hosts = zapi.item.get( {
"groupids": "4",
} )
"fil ter": {
"key_ ": "agent.versi on"
} ,
"output" :
"lastvalue",
"hostid"
O código fica mais legível e também mais fácil de ser
compreendido. Os sites que eu recomendo são:
)> http://jsonlint.com/
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
};;-- https://jsonformatter.curiousconcept.com/
O primeiro é bem mais simples e faz uma validação e formatação
de maneira mais rápida. O segundo tem mais opções para validar e
formatar o código usando tabulação ou mesmo uma saída
compactada.
Para usarmos essas duas ferramentas, basta copiarmos o
código, colarmos no campo correspondente no site e clicarmos no
botão para validar o código. Tudo estando correto, a ferramenta irá
formatar o texto corretamente e estará pronto para ser incluído no
código.
6.1. Zapix
Temos também ferramentas off-line para validação de JSON. A
ferramenta Zapix é mais que um validador. Com ela, também
podemos fazer requisições à API do Zabbix. Para usá-la, basta
fazer o download na URL https://bitbucket.orgNedmak/zapix
/downloads e descompactar o arquivo baixado em um diretório de
sua preferência. Já dentro do diretório descompactado, você vai
encontrar o arquivo api.html. Clique duas vezes nele para abrir a
ferramenta em seu navegador. A tela inicial da ferramenta é
apresentada a seguir:
Zap1x
.... - -
Para configurar a conexão com a URL da API do Zabbix, basta
clicar no link Connect, localizado no canto superior esquerdo da
tela. Surgirá a seguinte tela para configuração:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Connection manager
Host
http://192168 O 23fzabbJx
Logm
Admtn
Password
X-OEBUG SID
Store Connect .+
Stored connec tions
1 Remove
Nesta tela, basta informarmos, no campo Host, a URL de
conexão à API (a mesma da interface web do Zabbix). Caso a
interface web do Zabbix esteja presente na raiz do seu servidor
web não se faz necessário incluir o /zabbix. Insira os dados de ,
Login e Password. Se desejar, pode gravar a conexão cl icando no
botão Store. O próximo passo é clicar no botão Connect.
Para começar a fazer asrequisições, basta incluir o método e os
parâmetros nos campos correspondentes. Observe como fica o uso
do método host.get passando os parâmetros para uma consulta
simples:
..
Zap1x
......
1
1
iJi JO!i~-~.ISOH -
·J•...,...1·1.r • . ,,.,,,•1 t
~u;r. -.<n!·,
-.r.n• •• tH'I n:•
"'t.;;n:r ·1Cl!-C.º.
-ain• ~.,·
,.., - ........
1·:1 ..aoe•1•:.r "lllJU!~·,._"·0tit".9l•
.,.,,.. n1.1•• ~i·
Podemos observar no canto superior direito a requisição que foi
feita de acordo com os parâmetros passados ao método host.get e
também com o token de autenticação. Na parte inferior da imagem,
temos a resposta no formato JSON dos dados retornados de
acordo com a requisição. Além do parâmetro host, que foi
solicitado como saída da requisição, temos também o parâmetro
hostid, que é padrão nas requisições deste método.
Temos também uma ferramenta presente no próprio Python para
utilizarmos com comandos executados no terminal. É o caso da
utilização do curl, conforme vimos no tópico 1.4.
Vamos ao seguinte exemplo, após já ter obtido o token de
autenticação:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
-curl - X POST - H 'Co n t ent - Type : a pplication/j son'
' {" J.llarams": {"output":"shorten","host " : "Zabbix
server", "limi t": O}, " j sonrpc" : "2. O", " meth o d":
"hos t .get", " a uth " :
"4ed 65le2a af09d5225d834986c 4adf3b", " i d": 1 }'
h ttJ.l) : //local host/ zabbi x / a p i _ jsonrpc . php
A saída da execução anterior será:
{ " j sonrpc": "2 . O", "resul t " : [ { " hostid": "10 0 84"},
{"hostid " : "l010 6"}, {"hostid " : "l0107"} ] ,"i d":l }
Para deixarmos essa saída com uma leitura mais organizada, de
forma que possamos entender melhor o resultado, direcionamos o
comando para o Python com a opção -mjson.tool. A nova
execução do comando será na seguinte forma:
curl - X POST - H 'Cont ent - Type: application/j son'
- d
'{"params": {"output":"shorten","host" : "Za bbix
server", "limit" : O}, " j sonrpc" : "2. O", "meth o d":
"host .get", " a uth":
"4ed65le2aaf09d 5225d834986c 4adf3b", " i d": l }'
h t t p:/ /local host / zabbi x/ap i _ jsonrpc . php python
- mjson.tool
O resultado fica com uma saída mais legível:
" i d": 1 ,
"j sonrpc" : " 2 . O",
"re sult ":
" hostid ": " 10084"
} ,
"hostid": " 1010 6"
},
" hostid": " 1010 7"
}
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
7
Formatando a Saída
das Requisições
Até agora, realizamos as requisições sem fazer qualquer tipo de
tratamento, apenas verificamos a saída impressa na tela. Agora
não faremos apenas o uso da API - também incrementaremos
nossos códigos com a inclusão de estruturas para verificar algumas
condições, tendo como resultado os valores formatados para uma
leitura mais clara.
O uso das ferramentas vistas no Capítulo 6 é bom para estudos e
verificação dos dados requisitados que recebemos no formato
JSON. Porém, para uma leitura mais humana, ou seja, apenas dos
valores provenientes das requisições feitas, precisamos utilizar
blocos codificados com estruturas de dados para alcançarmos os
valores que poderão estar presentes em listas, dicionários e outros
tipos de dados, conforme já foi explicado no tópico 1.5. A tabela a
seguir mostra a relação dos tipos de dados entre Python e JSON:
JSON Python
object dict
array /ist
string unicode
number (int) int, long
number (real) f/oat
true true
false false
nu// none
Esta tabela foi adaptada de https://docs.python.org/2/l ibrary
/json.html.
Sabendo que na documentação oficial do Zabbix sobre
determinado método é solicitado como parâmetro um objeto
(object). você pode associá-lo com o tipo de dados dicionário (dict)
em Python. Outro exemplo é um método que solicita como
parâmetro um array, no qual em Python está relacionado com um
list.
No tópico 3.3, foi demonstrado um exemplo de formatação de
saída utilizando a estrutura for ao fazer uma requisição com o
método host.get, onde formatamos a saída para exibir os nomes e
IDs dos hosts.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Mostrarei agora exemplos para formatar a saída das requisições
e explicar com alguns detalhes os tipos de dados convertidos de
JSON para Python.
Lembre-se de que já entrei em detalhes sobre os parâmetros
comuns do método get no tópico 4.3. Saber a diferença entre eles é
crucial no momento de fazer sua requisição com os valores
desejados. Isso já poupa um pouco o trabalho de fi ltrar os registros
da requisição. Porém, formatar a saída é outra história. Precisamos
entender como esses elementos são armazenados nos tipos de
dados da linguagem de programação - neste caso, Python.
7 .1. Formatando a saída da requisição
do exemplo mostrado no tópico 5. 7 .2.1
No tópico 5.7.2.1 vimos um exemplo utilizando o método
history.get. A requisição foi armazenada em uma variável
chamada historico. Ao executarmos o código, teremos uma
variável do tipo list, com 3.783 elementos, de acordo com os
parâmetros passados. Esta variável pode ser observada na figura a
seguir:
Name Type Size: Yalue:
~Ofko m.~783 ((uºhtaid" u'lJ668', u•ni•: u••s&elJI', u•val1.1e': v"S9.69M' , u"Clock': u'l•ll . . .
Utilizando o explorador de variáveis da IDE Spyder, ao clicarmos
duas vezes na variável historico, teremos acesso aos elementos
da lista. Cada elemento da lista (também pode ser chamado de
índice) é um dicionário, conforme podemos observar na figura a
seguir:
lndex Type Size
[~~~~.~~] cfict 4
1 cfict 4
2 dict 4
3 dict 4
4 dict 4
5 dict 4
6 dict 4
7 dict 4
8 dict 4
9 dict 4
10 dict 4
11 dict 4
12 dict 4
13 dict 4
14 cfict 4
15 dict 4
16 dict 4
17 dict 4
18 dict 4
19 dict 4
20 dict 4
?1 ... ,... 4
Value
{u' itemid' : u '23668' , u'ns': u'4560138',
u'value ' : u ' 39.6000', u'clock' : u'14386 •..
{u' itemid' : u'23668', u'ns ' : u'606322530 ' ,
u' value ' : u'40.0000 ' , u'clock': u'143 . . .
{u'itemid ' : u'236'68', u'ns ' : u'359596042 ' ,
u'value': u'39.4000', u'clock': u'143 ...
{u' i tenrid': u'23668 ' , u'ns': u'665785765',
u' value': u'39.6000 ', u'clock': u'143 ...
{u'iteJllid': u'23668', u'ns': u'879789824 ' ,
u'value': u'39.9000', u'clock': u'143 . . .
{u' itemid' : u '23668', u"ns ': u'346500481',
u'value': u ' 39 .8000', u'clock' : u'143 ...
{u' itemid' : u'23668', u'ns ' : u'738119850',
u' value': u'39.8000 ' , u'clock': u'143 . . .
{u'itemid ' : u'23668', u'ns': u'33470392',
u• value': u'39.6000', u'clock' : u'1438 ...
{u' itemid': u' 23668' , u'ns': u'S49818930",
u' value' : u'40.0000 ', u" clock" : u'l43 . . .
{u'itemid' : u'23668', u'ns ' : U'235125808 ' ,
u'value': u'39.5000 ' , u'clock': u'143 ...
{u" itemid ' : u'23668', u'ns' : u'374474688",
u' value' : u'39.8000', u'clock ': u'l43 ...
{u' itenrid' : u'23668 ', u'ns': u'684474290',
u' value': u'40.0000 ' , u'clock': u'l43 . . .
{u' itemid ' : u'23668', u'ns': u'733322561',
u'value': u'39 .9000' , u'clock': u'143 ...
{u'itemid ' : u'23668 ' , u'ns': u'936860170',
u' value': u'39.0000 ' , u' clock ': u'143 . . .
{u' itemid' : u'23668', u'ns': u'330060241' ,
u'value': u'39.6000 ' , u'clock': u'l43 ...
{u' item.id ' : u'23668 ' , u'ns ' : u'958501485',
u'value ' : u'39.6000 ' , u'clock' : u'143 . . .
{u'itenrid': u'23668 ' , u'ns': u'185536115',
u'value': u'39.9000', u'clock': u'143 ...
{u'item:id ' : u'23668', u'ns': u' 401828565 ' ,
u' value' : u'39.6000', u'clock': u'143 ...
{u' itemi d ' : u'23668 ' , u'ns': u'508400923',
u' value' : u ' 38.8000 ", u'clock': u'143 . . .
{u' itemid' : u'23668', u'ns': u'678588922',
u'value': u'38.6000 ' , u'clock': u'143 ...
{u 'itemid ' : u'23668' , u'ns ' : u'779267149',
u' value' : u'39.3000", u'clock': u'l43 ...
{u' i temid' : u '23668 ' , u'ns': u'961880715',
D
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Dentro de cada elemento (ou índice), temos acesso às
informações que desejamos imprimir na saídada execução dos
nossos códigos. Neste caso, precisamos correr toda a lista, acessar
os dicionários e obter os valores presentes em cada dicionário.
Utilizaremos a instrução for para interagir com os elementos da
lista. Observe o código a seguir:
historico = zapi . history.get( {
"itemids":
} )
23668
] ,
"hi story": O,
"output": "extend",
"time from": " 1438387200",
"time till": " 14 3 92 50 95 9"
for x in historico:
print x [ "clock"], "- ", x["value" ]
Neste exemplo, a única alteração com o código mostrado no
tópico 5.7.2.1 é a remoção do print historico para a inclusão da
instrução for, presente nas últimas duas linhas.
Este código faz a requisição do histórico de coletas do item
23668 em um determinado período (veremos como converter datas
em Python no tópico 7.3). Por padrão da propriedade extend do
parâmetro output, a saída trará todas as informações do histórico,
conforme pode ser observado na imagem a seguir:
Kev Type Size Value r ...... -........... 'i .
l.:~~:~ .... .J umcode 1 1438642469
itemid unicode 1 23668
n:s unicode 1 4560138
value unicode 1 39 . 6000
Podemos observar que temos as seguintes chaves neste registro:
)> clock
» itemid
» ns
» value
No código, foi solicitado imprimir apenas os valores clock e
value. Neste exemplo, não foi necessário imprimir o itemid, pois a
requisição fora direcionada ao itemid 23668, conforme a utilização
do parâmetro itemids na requisição. A saída após a execução do
código é a seguinte:
1439250 358 - 39.100 0
1439250388 - 39.300 0
1439250 418 - 39.100 0
1439250448 - 38.800 0
1439250478 - 39.100 0
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
1439250509 - 39.2000
1439250538 - 39.30 00
1439250568 - 39. 0000
1439250598 - 39. 1000
143925{)628 - 38.6000
1439250658 - 39.20 00
1439250688 - 38.90 00
1439250718 - 38.50 00
1439250748 - 39.10 00
1439250778 - 39.20 00
1439250808 - 39.3000
Omitimos alguns valores, devido à requisição ter retornado 3. 783
registros.
Dica: quando obtiver dados de uma requisição à API
e estes forem armazenados em uma lista, utilize a
instrução "for" para ter acesso aos valores das
propriedades.
Obs.: o parâmetro output e countOutput são
ignorados pelo método history.get. Ao selecionarmos
esses parâmetros em uma requisição, esta não terá
o efeito esperado. Por exemplo: poderíamos
explicitar no output do exemplo deste tópico apenas
a saída das propriedades clock e value. Já para
imprimirmos a contagem dos registros, utilizamos a
função len() para ter o efeito esperado pelo
parâmetro countOutput. O código ficaria conforme a
seguir:
p rint "Quantidad e d e registros d a requ is ição: "
len (historico )
No momento em que escrevo este capítulo, os parâmetros
output e countOutput do método history.get ainda não tiveram
uma solução pelo time de desenvolvimento da Zabbix SIA. Esse
problema foi relatado e registrado no sistema de suporte oficial do
Zabbix como ZBX-5169 e ZBX-7750. Pela informação disponível na
URL https://support.zabbix.com/browse/ZBX-5169, este problema
estará resolvido na versão 3.0 do Zabbix.
7 .2. Formatando a saída de requisições
que se relacionam
O exemplo que será demonstrado neste tópico visa imprimir os
IDs dos hosts, seu nome, o IP e o tipo de interface presente em
cada host. Para imprimirmos o 1 P e o tipo de interface de cada host,
é preciso fazer uma requisição ao método hostinterface.get para
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
termos acesso a essas informações coletadas via host.get.
Primeiro, fazemos as requisições aos métodos e armazenamos
em variáveis:
# Obtendo l ista de hosts
hosts = zapi.host.get{{
"output": [
"hostid",
"na.me"
} )
# Obtendo l ista de endereços IP
interfaces = zapi.hostinterface.get ({
"output": [
} )
"hostid",
"ip",
''type"
Agora, iremos correr as duas listas que foram geradas e
armazenadas nas variáveis hosts e interfaces. Observe o seguinte
código:
for vetor hosts in hosts:
for vetor interfaces in interfaces:
if vetor_ interfaces ["hostid"]
vetor_h©sts['hostid']:
print
vetor_hosts['hostid'],vetor_hosts['narne' ] ,"- IP
-", vetor_interfaces["ip"]," - Tipo de
int erface:", vetor_interfaces["type"]
Primeiro, corremos a lista armazenada na variável host e em
seguida corremos a lista armazenada na variável interfaces. Nessa
segunda iteração, fazemos a verificação com a instrução if para
verificar se o hostid presente na lista interfaces coincide com o
hostid da lista hosts. Sendo verdadeira, a instrução será impressa
na seguinte ordem:
1. 10 do host
2. Nome do host
3. IP da interface do host
4. Tipo de interface do host
Se o leitor observar, é necessário correr a lista interfaces devido
a um único host poder ser monitorado por mais de uma interface,
como, por exemplo: Zabbix Agent, SNMP, JMX etc. Isso explica a
utilização de um for dentro de outro, pois precisamos verificar se
um host tem mais de uma interface cadastrada para ser exibida na
saída da execução do código. Veja o resultado da execução com os
hosts cadastrados em nosso ambiente de testes do livro.
10084 Zabbix server - IP - 127 . 0 . 0 .1 - Tipo d e
int erfac e: 1
1 0106 Cable Modem - IP - 127 .0. 0 .1 - Tipo de
int erface: 1
10107 Cliente - IP - 127 . 0 . 0 .1 - Tipo d e
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
interface : 1
10109 TesteJanssen - IP - 192 .168.2. 108 - Tipo
de interface: 1
10142 nmap - I P - 192.168 . 0 .5 - Tipo de
interface: 1
10167 HostExemplo - IP - 127.0.0 . 1 - Tipo d e
interface: 1
10168 Curso API 1 - IP - 192.168.0.5 - Tipo de
interface: 1
10169 Curso API 2 - IP - 192.168 . 0 .5 - Tipo de
interface : 1
10170 Curso API 3 - IP - 192.168 . 0 .5 - Tipo de
interface: 1
10171 Curso API 4 - IP - 192. 168 . 0 .5 - Tipo de
interface: 1
10172 Curso API 5 - IP - 192.168.0.5 - Tipo de
interface : 1
10173 Curso API 6 - IP - 192.168 . 0 .5 - Tipo de
interface : 1
10174 Curso API 7 - IP - 192.168 . 0 .5 - Tipo de
interface: 1
10175 Curso API 8 - IP - 192.168 . 0 .5 - Tipo de
interface: 1
10176 Curso API 9 - IP - 192.168 . 0 .5 - Tipo de
interface : 1
10177 Curso API 10 - IP - 127.0.0.1 - Tipo de
inte rfa ce: 2
10178 Curso API 11 - IP - 192 . 168.0 . 5 - Tipo de
interface: 1
10179 Curso API 12 - IP - 192 . 168.0 . 5 - Tipo de
inter face: 1
10179 Curso API 12 - IP - 127 . 0.0.1 - Tipo de
interface: 4
10179 Curso API 12 - IP - 127.0.0.1 - Tipo d e
interface: 3
Podemos observar neste exemplo que temos um host com mais
de uma interface cadastrada, que é o host Curso API 12. Também
podemos observar que o host Curso API 10 tem o tipo de interface
diferente dos demais. Ambos os hosts estão destacados no código
em negrito. Fica como exercício para o leitor exibir o nome da
interface em vez de seu código.
7 .3. Convertendo datas
Alguns métodos da API trabalham com tipos de dados timestamp,
também conhecido como tempo de época. Você já deve ter
observado que em alguns códigos mostrados até aqui nós não nos
preocupamos em formatar as propriedades que retornam valores
nesse formato.
Eu recomendo o site http://www.epochconverter.com/, onde é
possível converter manualmente um valor de época para uma data
legível. Este site também mostra como converter esse formato em
várias linguagens de programação e outras ferramentas, tais como:
sistemas operacionais, SGBDs etc.
Como esta obra está focando em consumir a API do Zabbix com
Python, explicaremos as maneiras de conversão nessa linguagem.
Primeiramente, é preciso importar a biblioteca t ime em nosso
código, de acordo com o exemplo a seguir:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
import t ime
Para obtermos o tempo atual, basta fazermos a chamada à
função time(). A seguir, o exemplo para imprimir o tempo atual:
print "Tempo atual em timestamp é:", time. t ime()
O resultadoé:
Tempo a t ua l e m timest amp é: 14448360 21.62
Para convertermos esse valor em data legível, usamos a função
strftime, que converte o timestamp em uma string de acordo com o
formato especificado. Exemplo:
print time.strftime("%d/ %m/ %Y %H : %M : %S",
time.localt ime(l444836021.62))
O resultado será:
14/ 1 0 /2015 12:20:21
Obs.: não é necessário retirar as casas decimais do
valor timestamp.
Vamos agora converter uma data legível para formato timestamp
usando a função strptime. Vamos converter a data 14/10/2015
14:35:00:
print time.mktime( t ime.strptime('l4/10/210 5
14:35: 00', '%d/ %m/ %Y %H:%M:%S' ) )
O resultado será:
4284984900 . 0
Não se espante com este último resultado. Isso aconteceu
porque formatamos a data para os padrões usados em nosso país.
Para comprovar o resultado, basta convertê-lo usando o exemplo
anterior a esse, ou mesmo no site mencionado no início do tópico.
Agora você está apto a trabalhar com datas para gerar seus
relatórios com os dados extraídos de métodos como history.get,
event.get, item.get, entre outros.
No Capítulo 9 veremos outros exemplos com conversão de datas.
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
8
Automatizando Tarefas
Trabalhar diretamente com a interface do usuário quando é
necessário executar atividades repetitivas é uma tarefa árdua em
qualquer circunstância. Para suprir erros e lentidões na execução
dessas tarefas, é altamente recomendado o uso da API para
agilizar quaisquer processos, seja de ativação de hosts, associação
de templates, habilitação de itens etc.
Neste capítulo veremos alguns exemplos que lhe darão ideias
para fazer seus próprios códigos para deixar seu ambiente
realizando tarefas automáticas e livres de falhas de configurações
que estão sujeitas a acontecer através de um processo manual.
8.1. Desabilitar automaticamente itens
não suportados
Durante o processo de monitoramento pode ocorrer de alguns
itens dos hosts monitorados apresentarem situação Not
supported. Isso, na maioria das vezes, acontece quando
associamos templates ao host monitorado e o template possui itens
que não são suportados pelo host a ser monitorado. Por exemplo:
você associa um template que possui itens do tipo IPMI e o seu
host não tem suporte a esse protocolo. Outro exemplo básico é
você criar um UserParameter e, por algum erro de configuração ou
execução, o servidor Zabbix não conseguir coletar a métrica desse
item.
O exemplo que veremos agora tem o intuito de desabilitar todos
os itens não suportados que forem encontrados no ambiente de
monitoramento. A princípio, vejamos como fica o código que faz a
requisição apenas para listar a quantidade de itens não suportados.
iten s = zapi .item.get ({
} )
"output": "ext e nd",
"fil ter": {
"st ate" : 1
} ,
" count output": True
print " Quantidad e d e i tens nã o suportados:
" ,itens
Utilizamos o parâmetro filter para retornar apenas os itens não
suportados, representado pelo número 1. Não podemos confundir
as propriedades state com status. A primeira retorna a situação em
que o item se encontra (normal ou não suportado) e a segunda
representa o estado em que o item se encontra (habilitado ou
desabilitado). A saída da execução do código será:
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Quantidade de itens não suportados: 19
Vamos observar a tela a seguir, onde podemos visualizar o painel
Status of Zabbix do dashboard principal na interface web do
Zabbix.
Parameter Value Oetails
Z<1bbix .suv .. r i.s runníng Yti loc;ilhoru 1oos1
trumber of kosts (enabledld1.sabl~templah;s) 51 2/S/-4
Number of itams tenable<l/disablêd/not supporte<I) 10'1 97 / 6 / 6
Numbe.r of trlggers (emobled/dis.abled ( problem/okJ) 57 57 /o [ 56]
Numbu of unrs (onlína) l l
Requhed "Serve.r perfonnancer oe\;I vaiue3 per zecond 1.59
Conforme indica a seta em destaque dentro na imagem, temos
listados seis itens não suportados, diferentemente do que foi
retornado na execução do código. Isso acontece porque a interface
web do Zabbix retorna apenas os itens não suportados dos hosts
monitorados, ou seja, dos hosts que estão com o monitoramento
habilitado. Portanto, iremos incluir em nosso código mais um
parâmetro, pois nosso intuito é desabilitar apenas os itens não
suportados dos hosts em monitoramento. Caso seja de seu
interesse desabilitar todos os itens não suportados de todos os
hosts, apenas ignore esse novo parâmetro.
O código com a adição do novo parâmetro ficará conforme a
seguir:
itens = zapi. item.get ({
} }
"output": "extend",
"filter": {
"state": 1
} ,
"monitored": True,
"countoutput": True
print "Quantidade d e ite ns não sup ortados:
",itens
Portanto, ao incluirmos o parâmetro monitored, teremos o
retorno apenas dos itens não suportados dos hosts que estão em
monitoramento. E o resultado da execução do código será:
Quantidade de itens não suportados: 6
Vamos agora ao objetivo deste tópico, que é desabilitar
automaticamente os itens não suportados que foram encontrados
em nosso ambiente.
Observe o seguinte código:
itens= zapi. item.get ({
"out put ": "extend",
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
"filt er": {
" stat e" : 1
} I
" mon i t o red": True,
f o r x in i t ens:
zapi . item. updat e ( {"itemid" :
x [ ' ite mid' J , "status": 1 })
Repare que tiramos o parâmetro countOutput e também a linha
responsável por imprimir a quantidade de itens não suportados. Por
que fizemos isso? Porque o parâmetro countOutput retorna
apenas a quantidade de itens encontrados na requisição. Sendo
assim, não seria possível percorrermos o for em busca dos itens e
atualizar o seu status. A instrução for é utilizada para fazer a
atualização apenas dos itens encontrados na requisição, sendo
mais eficaz e tomando menos tempo de processamento do nosso
servidor.
Com o resultado da execução do código, nosso dashboard já terá
a informação atualizada:
status of Zabblx
Paramet er Value Details
Zabbht sarver is running Yes locitlhoit: 10051
Number of ho5ts (enabl!!<l/disabl@d/templates) 51 2/'S/llA
Number of items (enabled/dlsabled/not supported) 109 97/12/0
Ncrmber of trigg<>rs (ecnabled/disabled (problecm/ok)) 52 52 / 4 [1 1}
Number of users (onlir>e) 3 1
R.equirerl serve..r p-e.rfonnarn:e, nelr, valu6".> per ~ond 1.48
Esse recurso é muito interessante para corrigir falhas em nosso
sistema de monitoramento, visando, em paralelo, melhorar o seu
desempenho, já que desabilitar itens não suportados melhora o
VPS do servidor, conforme pode ser comparado entre as duas
imagens anteriores, na última linha do painel, onde está escrito
Required server performance, new values per second.
Logicamente, se você consertar alguma falha em um desses itens,
o VPS tende a aumentar. Porém, você estará utilizando o potencial
do servidor para utilizar um recurso em funcionamento, e não um
recurso que não lhe trará métricas de seu ambiente.
8.2. Cadastrar hosts automaticamente a
partir de uma lista em arquivo
Imagine as seguintes situações.
1. Você precisa incluir no monitoramento um conjunto com mil
hosts, e esta tarefa não poderá ser feita via autobusca, por
motivos diversos.
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
2. Você foi escalado para importar uma base com 25 mil hosts de
outro NMS (Nagios, Cacti etc.) e precisa, a princípio, incluir os
hosts e seus IPs na base de dados do Zabbix.
Diante de uma das duas situações, nós podemos utilizar a API do
Zabbix para automatizar esse processo e cadastrar
automaticamente os hosts necessários. Podemos fazer esse
processo de várias maneiras. Mostraremos a forma de importação
de um arquivo CSV separado por ponto-e-vírgula (;). O arquivo é
facilmente exportado para esse formato de qualquer base. Portanto,
não é nosso objetivo informar como o leitor vai adquirir esses
dados. Mostraremos um esboçode um arquivo que será utilizado
para a importação que será executada em nosso exemplo. O
arquivo deverá seguir o padrão:
Hos tna me;IP
A seguir, um exemplo de arquivo nesse formato:
host automat i c o l ; l92 . 168 .10 .l
hos t automat i c o 2 ; 192 . 168 .10 . 2
hos t automat i c o 3 ; 192 . 168 . 1 0 . 3
hos t automat i c o4; 192 . 168 .10 .4
hostautomat i c o5; 192 . 168 .10 .5
Podemos observar que cada linha presente no arquivo é um host
que será cadastrado na base de dados do Zabbix.
Uma das vantagens da linguagem Python é a grande variedade
de bibliotecas presentes para utilizarmos em nossos códigos. Eu
poderia mostrar exemplos utilizando manipulação de arquivos com
funções de abertura, leitura etc. Porém, veremos esse exemplo
utilizando a biblioteca csv, que deixa mais fácil o trabalho de leitura
de arquivos que contenham informações diferentes em cada linha
presente.
A ideia do exemplo é cadastrar os hosts passando o nome e ip
que serão importados do arquivo hosts.csv e também com as
informações de grupo e templates. Cada host será cadastrado no
grupo Linux Servers e associado ao template Template OS Linux,
além de cadastrar a interface do agente Zabbix com seu respectivo
IP. A seguir, o código dessa automação:
#!/usr/bin/e n v p y t hon
# - *- coding : utf - 8 - *-
f r om zabbix_api i mp o r t ZabbixAPI
i mp o r t c s v
zapi = ZabbixAPI{server=" h t tp : //192.168 .2.113
/ zabbix" )
zap i. log in( "Admi n " , "zabbi x" )
a rquivo= c s v . r eader (open{ ' /tmp/h osts . csv' ),
del imi ter=';' )
f o r [hostname,ip ] i n arquivo:
hos tcriado = zapi .host.create {{
"host": hos tna me,
"st atu s" : 1,
"interf aces":
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
"t ype": 1 ,
"main": 11
" useip" : 1,
"ip" : i p,
"dns": "",
"port" : 10050
] ,
"groups": [
"groupid": 2
] ,
"templat es":
"templateid": 10001
O código é bem simples: ele abre o arquivo /tmp/hosts.csv e
informa o seu delimitador. Corre as linhas encontradas no arquivo e
faz a chamada do método host.create para cada registro
encontrado e cadastra o host no Zabbix de acordo com as
informações de cada registro, ou seja, nome e IP, além das
informações em comum, tais como: tipo de interface, grupo de host
e template.
Apenas para efeito de informação: com esse código, importando
dados de um arquivo com 250 linhas contendo o nome e o IP do
host, a execução leva em média um minuto e cinco segundos em
uma máquina virtual com 512 MB de RAM e processador Intel i7
4500 a 1.80 GHz. É uma economia de tempo se comparado com a
criação via interface web, que em média leva em torno de 25
segundos para cadastrar apenas um host com as mesmas
informações desse exemplo.
8.3. Montar árvore de serviços de TI
automaticamente
Um dos pontos positivos de se trabalhar com a API do Zabbix é a
facilidade de executar tarefas com um ganho de tempo que não se
compara ao fazer a mesma tarefa pela interface web. Vimos no
tópico 8.2 (o exemplo de cadastramento de hosts) como é simples
automatizar uma tarefa repetitiva para ganhar tempo e ser mais
produtivo. Aqui veremos como montar a árvore de serviços de TI de
todo o seu ambiente. Este exemplo é apenas um teste e não
deverá ser executado em ambiente de produção antes de testá-lo,
pois ele irá remover toda a árvore existente e cadastrar todos os
hosts com suas triggers separadas por grupos de hosts.
O código que será mostrado a seguir é mais elaborado, usando
chamadas de funções, criação de listas adicionais, além de
utilização de variáveis nas requisições a API. O leitor deverá tomar
cuidado ao tentar validar as requisições contidas nos códigos
mostrados neste tópico nas ferramentas demonstradas no Capítulo
6. Ao contrário das linguagens de programação, essas ferramentas
não convertem os valores contidos nas variáveis, o que as fazem
invalidar as requisições.
O código proposto é mostrado a seguir:
#!/usr/bin/ e nv pyt hon
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
# - *- coding: utf-8 -*-
from zabbix_api import ZabbixAPI
zapi ZabbixAPI(server="http : //192 . 1 68.2 . 1 01
/zabbix" )
zapi .login ("Admi n", "zabbix")
def obterGrupos():
hostgroups = zapi . hostgroup.get({
))
"output": "extend",
"real hosts": True
listaGrupos = [ l
for x in hostgroups:
print x [ 'name']
l istaGrupos += [x['name']]
return listaGrupos
def obterGrupoid(nomeGrupo):
groupid = zapi.hostgroup.get({
"output": "extend",
"filter":
"name": nomeGrupo
}
} ) [O ] [ 'groupid' l
return groupid
def obterHosts(nomeGrupo):
hosts_grupo = zapi.host.get({
"groupids": obterGrupoid(nomeGrupo),
"output":
"host"
} )
l istaHosts = []
for x in hosts_grupo:
print x [ 'host']
listaHosts += [x['host'] J
return listaHosts
def obterHostid(nomeHost ):
hostid = zapi.host.get({
"output" : "hostid",
"filter" :
"host": nomeHost
} ) [O] [ 'hostid']
return hostid
def obterTriggersHosts (nomeHost):
triggers = zapi.trigger.get( {
"hostids": obterHostid(nomeHost),
"expandDescription": "true",
"expandComment": "true",
"expandExpression": "true"
} )
for x in triggers:
p rint x['description'J
def obteritens(nomeHost) :
itens= zapi .item.get( {
"hostids": obterHostid(nomeHost),
"with_triggers": True,
"selectTriggers": "extend"
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
l istaitens = [ J
for x in itens:
print x [ 'narne']
listaitens += [x['narne'J J
return listaitens
def obteriternTriggerid(nomeHost,norneitem):
triggerid = zapi.itern.get({
"output": "triggers",
"hostids" : obterHostid(nomeHost),
"with_triggers": True,
"selectTriggers": "triggerid",
"filter":
"narne": norneitem
} ) [O J [ 'triggers' J [O J [ 'triggerid']
return tri ggerid
def criarServicosPai(nomeGrupo):
zapi.service.create( {
"narne": nomeGrupo,
"algorithm": "1",
''shows la": "1",
"goodsla": "99.99",
"sortorder": "1"
} )
def obterServico5Pai(nomeGrupo):
parentid = zapi.service .get ({
"selectParent": "extend",
"selectTrigger": "extend",
"expandExpression": "true",
"filter":
"narne": nomeGrupo
}
} ) [O] [ 'serviceid' J
return parentid
def criarServicosFilho(norneHost,nomeGrupo):
zapi.service.create ({
"name": norneHost,
"algorithm": "1",
"showsla": ''1",
"goodsla": "99.99",
"sortorder": "1",
"parentid": obterServicosPai(nomeGrupo)
} )
def obterServicosFi lho (norneHost):
parentidChild = zapi.service.get({
"selectParent": "extend",
"selectTrigger": "extend",
"expandExpression": "true",
"filter":
"narne": nomeHost
} ) [O] [ 'serviceid' J
return parentidChild
def criaritensServicos(norneHost,nomeitern):
zapi.service .create ({
"narne": nome Item,
"algorithm": "1",
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
''showsla" : "1",
"goodsla" : "99.99",
''sortorder": "1",
"parentid": obterServicosFi lho (nomeHost),
"triggerid":
obteritemTriggerid(nomeHost,nomeitem)
} )
def obterServicos() :
itservices = zapi . service.get( {
"selectParent": "extend",
"selectTrigger": "extend"
} )
l istaServicos = [ ]
for x in itservi ces :
l istaServicos += [x [ 'serviceid'] ]
return listaservicos
def removerArvoreServicos():
for x in obterServicos():
zapi.service.deletedependencies( [x])
zapi.service.delete( [x])
def criarArvoreServicos() :
removerArvoreServicos( )
for nomeGrupo in obterGrupos():
criarServicosPai(nomeGrupo)
for nomeHost in obterHosts(nomeGrupo):
criarServicosFilho(nomeHost, nomeGrupo)
for nomeitem in obteritens(nomeHost):
criaritensServicos(nomeHost, nomeitem)
criarArvoreServicos()
Podemos observar que o código possui 15 funções. Explicaremos
cada uma delas a seguir.
8.3.1. Função obterGrupos
Esta função tem como objetivo retornar uma lista com os grupos
de hosts cadastrados no Zabbix. O uso do parâmetro real_hosts
faz com quesejam retornados apenas os grupos que tiverem hosts
como membros. Portanto, se você possuir um grupo de hosts
cadastrados sem nenhum host como membro, esse grupo será
ignorado pela requisição e não será criado na sua árvore de
serviços.
Esta função não requer o uso de argumentos para sua execução.
O comando print serve apenas para exibir os grupos que fazem
parte da requisição.
8.3.2. Função obterGrupold
Esta função tem como objetivo retornar o ID de um grupo
passando como argumento o nome do grupo de hosts.
A requisição à API feita nessa função passa o parâmetro filter,
que faz uma consulta através do nome do grupo de hosts passado
como argumento da função.
8.3.3. Função obterHosts
Esta função tem como objetivo retornar uma lista com os hosts
cadastrados no Zabbix que pertencem ao grupo de hosts passado
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
como argumento da função. Essa é uma função que chamamos de
wrapper, pois ela faz chamada a outra função, que no caso é a
obterGrupold. Observe que na requisição usamos o parâmetro
groupids para retornar a lista dos hosts. Só que não sabemos qual
é o 10 do grupo de hosts. Para isso, a requisição é passada
chamando a função obterGroupld, que irá retornar o 10 do grupo
pesquisado. Esse é o motivo de algumas funções usarem a
instrução return, que tem o objetivo de armazenar em uma variável
o retorno da execução da função.
8.3.4. Função obterHostld
Esta função usa a mesma lógica da função obterGrupolD.
Porém, ela irá retornar o 10 do host consultado por seu nome.
8.3.5. Função obterTriggersHosts
Esta função tem como objetivo apenas imprimir a descrição da
trigger na execução do código. Removê-la do código não
influenciará o resultado.
Observe que ela não tem a instrução return, pois seu propósito
não é obter o valor da requisição para ser passado adiante, apenas
para imprimir a descrição da trigger.
8.3.6. Função obterltens
Esta função tem como objetivo retornar uma lista com os itens. A
função necessita de um argumento, que é o nome do host. Ela
retornará uma lista contendo apenas itens que possuem triggers
que fazem referência à chave do item. Essa função é essencial no
código, pois será necessana para a função principal,
criarArvoreServicos, que depende da função obterltens para criar
os itens de serviço de cada host na árvore.
8.3. 7. Função obterltemTriggerld
Esta função tem como objetivo retornar o ID de uma trigger de
acordo com os argumentos passados na função, que são:
nomeHost e nomeltem. A requisição à API será feita buscando o
10 do host, que por sua vez chamará a função obterHostld, que
será responsável por retornar o 10 do host que será utilizado na
requisição. Você pode observar que o método utilizado nessa
função não é o trigger.get, e sim item.get. Isso porque é preciso
fazer essa relação entre host e item para obter o 10 correto da
trigger que está relacionada ao item e ao host. Observe que
fizemos um filtro com o nome do item passado como argumento,
para fechar essa relação e retornar o 10 da trigger correta.
Esta função é necessária para a função criarltensServicos.
8.3.8. Função criarServicosPai
Esta função tem como objetivo criar a primeira camada na árvore
dos serviços de TI que será exibida na interface web após a raiz da
árvore. Nesse contexto, essa camada é gerada com os nomes dos
grupos de hosts presentes na base de dados do Zabbix, que são
exibidos na interface web. Por esse motivo, o argumento passado
nessa função é o nome do grupo.
A seguir, uma imagem que representa a criação dessa camada:
$ Zabb.x s&rvers Avêrag:e Zabbt)'. ;igent O!! C\J!'S9 API 10 ts unr .. ac!@
8.3.9. Função obterServicosPai
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Esta função tem como objetivo retornar o 1 D do serviço de TI
(primeira camada após a raiz) que será utilizado na função
criarServicosFilho. A função faz a requisição passando como fi ltro
o argumento recebido, que é o nome do grupo do host.
8.3.1 O. Função criarServicosFilho
Esta função tem como objetivo criar os serviços de TI que
representam os nomes dos hosts associados ao grupo de host que
é passado como argumento. O parâmetro que destaco aqui é o
parentid, que recebe como valor o retorno da função
obterServicosPai, que é o serviceid, que será criado dentro dessa
camada.
A seguir, um exemplo com a imagem que representa a criação
dessa camada.
9 .. Zabbíx g:rver OK
éJ.. Testel•nssen OK
Zabbix •gent on Curso API 10 Is unre•chable for 5 minutes
Zabbi~ agent oo Curso API 10 i~ ul'reacl>able for S minute..
8.3.11. Função obterServicosFilho
Esta função tem como objetivo retornar o 1 D do serviço de TI
(segunda camada após a raiz, representada pelo nome do host)
que será utilizado na função criarltensServicos. A função faz a
requisição passando como filtro o argumento recebido, que é o
nome do host.
8.3.12. Função criarltensServicos
Esta função tem como objetivo criar os serviços de TI (terceira
camada após a raiz, representada pelos nomes dos itens
associados ao nome do host). A função recebe como argumento o
nome do host e o nome do item. O nome do host será utilizado no
parâmetro parentid, que chamará a função obterServicosFilho
para obter o ID do serviço de TI que possui o nome do host. Já o
nome do item será utilizado no parâmetro triggerid, que por sua
vez chamará a função obterltemTriggerld para recuperar o ID da
trigger que será utilizada no cálculo do SLA desse serviço.
A seguir, um exemplo com a imagem que representa a criação
dessa camada.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
1
~- Zabblx s<>rv<>rs
$ .. Zabblx seN&r
Í··- Host rlilme of zabbix aqent:d runnloo-Host name of zabbix ilqentd ,,ns chaoogd. on Ti?steJans:se:n
i
:··· Aq<>ITI: plro-Zabb1l' "'!!"ITI: or T"st..Jartn'!r> os om·l!acl>ai>le For 5 mlrutes
!·· Versíon of i:.abbix aqentídl runnlng-Version of ;:abblx arumt!dl \tas changed on Test>eJanssen
i-... l.talCimum number of proc&sses-Corrfigured max number of Drt>CaSse3 [s too foi.1 on Te-:stelaMS-en
i- Numb<>r of ro""'"" 1>RX4'n'!~-Too manv or<>ease'S rurriro on Te~Jª"'""'
'
r· fwmber of proc~-5ti·Too many proci!»es on TesteJaru:sen
i-- Proc:essor lcad ( 1 min av1>r.ui0 oer core l-Proc.esscr load is too high º" T~Ja"55""
'
i··· CPlJ S2 bme-01sk VO 1s overloaded on TesteJar.ssen
i-· Host ,,...,~·Hostl'arrn> .. as cf>arged on T~1>Ja"5~n
'
1 .. - Free S'-·1ao sea-ce 1n ~'o-Lack c.f free S\•tap space on Teste1anssen
i-- Svstem i~formatiof\- 1-'Mt information ·as ct>anged on TMt4'Jans5"n
'
!-· S vstem uptime-TesteJanssen has JUst be<>n restarted 127.0.0.1
!-· Checl wm of 51 - !!'tcloa~s-.d h ... beer> ckanoed .,.,. TesteJaMS!!'r>
'
, .. Free lnodg gn Sl Cperçentage l·Free inod@s is lep tban ZOO.§ on volume I
[.- Free disk ~pace °" Sl loerc .. ntaql')-F""' dlsk soace Is te~ .. tt>a~ 20•0 on volume /
'
L .. AvaifabJo:i; memory-lack gf a-vailable mt!morv on se.Ner Test:eJans.sen
ffi- curso APr 10
8.3.13. Função obterServicos
Esta função tem como objetivo retornar todos os serviços de TI
cadastrados. Ela foi criada para ser utilizada na função
removerArvoreServicos.
,.3.14. Função removerArvoreServicos
Esta função tem como objetivo remover completamente toda a
árvore dos serviços de TI cadastrada no ambiente. Ela faz chamada
à função obterServicos e utiliza um for para remover todos os
serviços de TI que forem retornados com essa função, inclusive
removendo as dependências relacionadas aos serviços de TI
listados.
8.3.15. Função criarArvoreServicos
Esta função tem como objetivo criar toda a árvore de serviços de
TI automaticamente. Primeiro, ela faz chamada à função
removerArvoreServicos para limpar completamente o ambiente
de serviços de TI. Em seguida, começa a percorrer a lista de
grupos obtida pela função obterGrupos. Cria a primeira camada da
árvore após a raiz chamando a função criarServicosPai. Para
cadagrupo de hosts encontrado no Zabbix com as condições
passadas na função obterGrupos, são criados novos serviços de
TI com os nomes dos hosts do grupo atual da lista. A última
instrução for percorre a lista obtida com a função obterltens e faz a
chamada à função criarltensServicos para cadastrar os serviços
de TI com os nomes dos itens associados a cada host.
A seguir, um exemplo com a imagem que representa a criação de
toda a árvore.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
1 tT services
Service Statu5 calcu lallon
e u,,, .. ltO'" ~tn. 11 •• ltttl - <hld ""' • P'Obl•m
Probltm. •f •t lnst - cM<I t..s • .,.,.bltm
~·"'· 1 •t ltut - <.Md hu o ~tm
e »ao API ~bltm, •J ot ltut - cM<I hu a problo"'
Problom. 1f •• ltnt - clóld t..s • p<Obltm
@ Çatdt f.':odtm Problt m. 1f •t lon - cMd h» • ptOl>lt tn
8 Ztbb!?s sttyta
"'°1>10"" 11 ot ltost - chold t..s • ~tm
Probltm. 11 at lout - cMd "°' • ~•m
Vimos um exemplo bem prático do que é possível fazer com a
API do Zabbix. O que parece ser uma tarefa complexa se reduz a
alguns segundos de execução do código, que não é tão complexo
quanto parece. Aqui, utilizamos não somente o conhecimento das
requisições à API do Zabbix, como também a lógica de
programação para produzir o resultado almejado.
Portanto, para concluirmos este capítulo, vale lembrar que o uso
da API se resume no que você deseja fazer, entender o que pode
ser obtido com as requisições através do uso dos métodos corretos
e usar a lógica. A solução não depende da linguagem de
programação. O exemplo pode facilmente ser portado para outras
linguagens.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
9
Gerando Relatórios
Veremos neste capítulo exemplos práticos de geração de
relatórios, com o objetivo de gerar saída dos dados que serão
consumidos da API.
9.1. Relatório de itens não suportados
Este relatório exibirá os itens que estão com status Not
supported. O relatório exibirá o id do host, o id do item, o nome do
item e o motivo pelo qual está como não suportado. A seguir temos
o código que gera esse relatório:
#!/usr/bin/env python
# - *- coding: utf-8 -*-
from zabbix_api import ZabbixAPI
zapi ZabbixAPI(server="http : //192 . 168.2 . 109
/ zabbix" )
zapi.login("Adrnin", "zabbix")
itens= zapi.item.get({
"output" : "extend",
"filter": {
"state": 1
} )
print "================================"
print "ID host - ID Item - Nome - Erro"
print " ================================="
for x in itens:
print x [ " hostid" J , "-", x [ "i temi d" J ,
x ["narne" J , "-", x ["error"J
"-" ,
print "================================"
print "Total de itens não s uportados:
",len(itens)
O relatório dispensa comentários, pois é muito simples e já vimos
uma requisição parecida no tópico 8.1. A seguir temos a saída da
execução do código:
ID host - ID Item - Nome - Erro
1 0084 - 23261 - Zabbix $4 $2 processes, in % -
No "ipmi p©ller" p rocesses started.
10084 - 23262 - Zabbix $4 $2 processes, in % -
No "java poller" processes s tarted.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
10084 - 23267 - Zabbix $4 $2 p rocesses, i n % -
No "srunp trapper" processes started.
10084 - 23328 - Zabbix $4 $2 p rocesses, in % -
No "vmware collector" p r ocesses start ed.
10084 - 23635 - Zabbix vmware cache, % free - No
"vmware collector"" p rocesses started.
10106 - 23666 - Nível de Potência Downstream -
Receive d val ue [ ] is not s u itable f or val ue type
[Numeric (fl o a t)]
10106 - 23667 - Nível de Potência Upstream -
Receive d val u e [ ] is not s u itable for val ue type
[Numeric (fl oat )]
10106 - 23668 - Relação Sinal Ruido - Rec e ived
value [ ] is not suitable for value type [Numeri c
(float}]
10106 - 23670 - Statu s - Timeout while executing
a s hell script.
10106 - 23672 - Teste de Ping - Unsupporte d item
key .
10109 - 23696 - Teste de cri acao de item -
Unsupporte d item key .
10084 - 23711 - apimemoryinactive - Invalid
firs t p arameter.
10107 - 23723 - Average disk read qu eue length -
Unsupporte d item key.
10107 - 23724 - Average disk write queue length
- Unsupported item key .
10107 - 23725 - File read bytes per second -
Unsupporte d item key .
10107 - 23726 - File write bytes per second -
Unsupported item key.
10107 - 23727 - Number of threads - Unsupported
item key .
10107 - 23745 - apime moryinactive - I nvalid
first paramet er .
1010 9 - 23896 - apimemoryinactive - Not
supported by Zabbix Agent
Total de itens não suportados: 19
9.2. Relatório de agentes do Zabbix
desatualizados
Este relatório exibirá os hosts que estão com os agentes Zabbix
desatualizados. Simularemos que a última versão é a 3.0 e
devemos informar o ID de um grupo de hosts. A seguir, temos o
código que gera o relatório:
#!/usr/bin/env python
# - *- coding: utf-8 - * -
from zabbix_api i mport ZabbixAPI
zapi = ZabbixAPI{server="http: //192.168.2.109
/zabbix"}
z a p i. login ("Admin", "zabbix")
gru po_hosts = zapi.item.get( {
"groupids": "4",
"filter":
"key_ ": "agent . versi on"
} ,
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
} )
"output": [
"lastvalue",
"hostid"
ultima versao = "3. 0 "
print "Relação dos hosts com Zabbix Agent
desatualizado."
print
"-------------------------------------------------"
print "ID - Host - Versao "
print
"-------------------------------------------------"
for x in grupo_hosts:
if x ["lastvalue"J < ultima versao:
host = zapi.host .get({ "hostids":x['hostid'J,
"output": ["name" ] })
print x ["hostid" ] , "-", host [ O] ["name"J,
"-", x["lastvalue"J
Neste código foram realizadas duas requisições à API. A primeira
requisição filtra os itens com a chave agente.version do grupo de
hosts 4 com o objetivo de recuperar o valor das propriedades
lastvalue e hostid do item. A segunda requisição é realizada
dentro da instrução for que percorre a lista gerada com a primeira
requisição. A segunda requisição é necessária para obter o nome
do host que será impresso no relatório. Ainda dentro da instrução,
fazemos a verificação do valor coletado do item com o valor da
variável ultima_versao. Se o último valor coletado for menor que o
presente na variável, serão impressos o 10 , o nome do host e a
versão do agente que se encontra desatualizado, conforme
podemos observar na saída a seguir:
Relação dos hosts com Zabbix Agent
desatualizado.
ID - Host - Versao
10084 - Zabbix server - 2.4.6
10109 - TesteJanssen - 2.4.6
10107 Cliente - 2.2.2
9.3. Relatório top 1 O CPU
Este relatório exibirá uma saída formatada em texto com os hosts
que mais utilizaram a CPU durante um período. A seguir, temos o
código:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from zabbix_api i mport ZabbixAPI
from operator import itemgetter
zapi = ZabbixAPI(server="http://192.168.2.116
/zabbix")
zapi. logirr ("admin", "zabbix")
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
chave "system.cpu.util[,user]"
itens = zapi.item.get({
"filter":
} )
"key_": chave
},
"selectHosts":
l '
"hostid",
"host"
"monitored": True
novoDicionario
for x in itens:
totalHost = O
totalValoritem
{}
o
mediaHost
historico
o
zapi.history.get({
} )
"hostids": x["hostid"],
"iternids": x ["itemid"],
"history": O,
"output": "extend",
"time from": "1447718399",
"time till": "1448323199"
for y in historico:
totalHost = len(hist-0rico)
totalValoritem += float(y["value"])
mediaHost = float("%.2f" % (totalValoritem /
totalHost))
novoDicionario [x ["hosts" J [ OJ ["host"] ] =
{"media" : mediaHost}
listaOrdem = sorted(novoDicionario.items(),
key=itemgetter( l ), reverse=True)
titulo = "TOP 10 CPU"
barra = " ===================================1'
print barra
print titulo.center(len(barra))
print barra
print '{0:2 } 1 {1 : 22) 1 {2 :4 )' .format("
#", "Rost","(%) ")
print "-----------------------------------"
contador = O
for z in listaOrdem[:lO]:
contador += 1
print '{0 : 2} 1 {1 :22)
{2:4}' .format(contadorr z[O ] , z [ l] [ "media"])
print barra
Neste relatório fizemos duas requisições à API do Zabbix. A
primeira é para selecionar os itens filtrados pela chave indicada na
variável chave e recuperar apenas os itens dos hosts que estão
com o monitoramento ativado. A segunda requisição é que irá
recuperar as informações dos históricos dos itens para fazer a
média de utilização de CPU.
Nesse código, a primeira iteração que fazemos é percorrer lista
de itens criada com a primeira requisição. Essa iteração será
responsável pela recuperação dos dados históricos de cada registro
da lista criada, ou seja, de cada host que foi encontrado na primeira
requisição. O total de .registros dessa lista será o total de hosts com
monitoramento ativo e que possuem a chave informada na variável
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
chave.
Ainda dentro do laço que percorre a lista itens, fazemos uma
nova iteração, dessa vez com a lista criada a partir da segunda
requisição (observe que essa segunda requisição se repetirá para
cada host encontrado na primeira requisição). Esse segundo laço
será responsável por somar o valor do item em cada registro
encontrado no histórico, de acordo com o período selecionado.
Portanto, esse laço tem o objetivo de calcular a média do valor do
item.
Finalizando o laço principal, armazenamos a média calculada em
um dicionário criado com o nome novoDicionario.
Para ordenarmos esse novo dicionário criado, importamos a
classe itemgetter da biblioteca operator. Isso porque o Python vai
armazenando os registros no dicionário na ordem em que eles vão
chegando. Existem várias maneiras de ordenar dicionários. O jeito
mais fácil é usando a classe itemgetter para ordenar o dici.onário
pela chave. No nosso exemplo, estamos ordenando o dicionário
pelos valores das chaves, que é o que nos interessa - por isso o
número 1 dentro dos parênteses no parâmetro key=itemgetter(1 ).
O reverse=True irá inverter a ordem, pois queremos listar do maior
para o menor, ou seja, os hosts com mais utilização de CPU. Isso é
o suficiente para ordenar os valores presentes nas chaves. O leitor
deve ficar atento ao ordenar dicionários pelos valores das chaves.
Por exemplo: ordenar valores do tipo string terá um resultado
diferente de valores do tipo f/oat. Por isso utilizamos conversões de
f/oat no código. Retire a conversão e você verá que o resultado
será diferente.
Observe que ordenamos o nosso dicionário armazenando-o em
uma nova variável, que chamamos de listaOrdem. O Python
definiu que o tipo de dados dessa nova variável é um list. Portanto,
basta percorrermos a listagem para imprimir os registros pela
ordem correta, o que é realizado no último trecho do nosso código.
A diferença é que percorremos a lista definindo quantos registros
serão lidos. Como estamos criando um relatório top 1 O, definimos
que a lista seria percorrida apenas pelos dez primeiros registros. O
restante do código para montar o relatório é apenas para formatar a
tabela que será impressa. Aqui o que vale é a sua imaginação na
formatação do relatório. Portanto, indico a leitura do seguinte
conteúdo: https ://does. python. org/2/tutorial/inputoutput. html.
O resultado do nosso relatório, após a execução do código, será
parecido com a saída a seguir:
TOP 10 CPU
# 1 Host 1 (% )
1 testeJanssen 1 15 . 57
2 nmap 1 4.38
3 HostExernplo 1 2.91
4 Zabbix server 1 2.67
5 Curso API 1 2.64
6 Curso API 2 2.19
7 Cu rso API 3 o
8 Cu rso API 4 o
9 Cu rso API 5 o
10 1 CursoAPIRernover 1 O
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
9.4. Relatório dos incidentes não
resolvidos
Este relatório irá apresentar os dados que visualizamos no
dashboard principal da interface web do Zabbix, exibido no painel
Last 20 issues. A imagem a seguir tem o exemplo desse painel:
from zabbix_api import ZabbixAPI
import time
zapi ZabbixAPI{server="http: / /192.168.2.10 9
/zabbix")
zapi.login {"Admin", "zabbix")
~;ij~fi~~~iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii!~~~gers = zapi.trigger.get {{
li "output": [ "description", "last change"] ,
Ho st A ssun t o Última alteração Idade Info rrnação Reconhecido Ações
"selectHosts" : ["hostid", " host "],
"selectLastEvent" : [ "eventid ",
Temperatura adma do pa dr;M, na sala --· 13-11-2015 08:43:24 1h 25m 3ês
Zabbf'.. a-gent on - :is Ul'raacl\ab!e for 5 minutes OS-1 1-2015 23~11!30 7d 10h 57m
Lack cf free s.'1ap space on - 5-11·2015 z3,01,zs 14 uh 1m O
;:;:::::===========================-
Imagine a seguinte situação: o gerente da equipe de incidentes
gostaria de receber um e-mail todos os dias pela manhã para ter
um controle dos incidentes não resolvidos, ordenado pelo maior
tempo do incidente, ou seja, o incidente que possuir o maior tempo
sem ter sido resolvido será exibido no topo do relatório. Ele não
quer ficar acessando a interface web do Zabbix todos os dias para
obter esses detalhes. Ele deseja utilizar esse relatório para cobrar
do supervisor da área a resolução dos problemas que estão
estourando o SLA.
A seguir temos o código que gera esse relatório:
#! /usr/ bin/ env python
# - *- coding: utf-8 -*-
2
"acknowledged ", "obj ectid", "clock",
"sortfield" : "lastchange",
"monitored": "true",
"ns"],
5 de 5 incidentes ex ibidos
"only_tr ue": " t rue",
"maintenance": "false",
"expandDescrip tion": True,
"filter":{"value":l)
} )
print "Host - Descrição - Última a l teração -
Idade"
print
''=====================================''
for y in triggers :
nome_host = y["h osts"] [ O] ["host" ]
idade= time.time{) - float {y["lastchange"])
pegadia =
"{ 0 .tm_yday}".format(time.gmt ime{idade))
d ia = int(pegadia ) - 1
d uracao = "dias {0 . t m_hour} horas {0 .tm_min}
minutos" . format {time.gmtime(idad e ) }
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
ultima_alteracao = time.strftime("%d/%m/%Y
%H: %M: %S",
time.localtime(float(y["lastchange"])))
print nome_host, "- ", y ["description"],
u ltima_alteracao, "- ", dia, duracao
"- \\
Podemos observar que em apenas uma requisição obtivemos os
dados que nos interessavam. Neste exemplo, vale destacar que os
parâmetros selectHosts e selectLastEvent irão selecionar o host
e o último evento relacionado à trigger que gerou o evento. Outro
parâmetro interessante é o expandDescription, que literalmente
traduz as macros contidas nas descrições das triggers.
Neste código utilizamos a biblioteca time para fazer a conversão
de datas e também obter o tempo em que o evento está ativo no
sistema.
Você pode ter observado que no código não tem a
implementação para envio do relatório por e-mail. Não é objetivo
desta obra ensinar como isso é feito.
O resultado da execução do código é mostrado a seguir:
Host - Descrição - Última alteração - I dade
xxxxx - Zabbix agent on xxxxx is unreachable for
5 minutes - 13/10/2015 16 :29 : 00 - 30 dias 16
horas 30 minutos
xxxxx - Lack of free swap space on xxxxx -
05/11/2015 23:01:28 - 7 dias 10 horas 57 minutos
xxxxx - Zabbix agent o n xxxxx is unreachable for
5 minutes - 05/ 11/ 2015 23: 11:30 - 7 d ias 10
horas 47 minutos
xxxxx - Zabbix agent on xxxxx is unreachable for
5 minutes - 12/11/ 2015 21:07:00 - O d ias 12
horas 52 minutos
xxxxx - Temperatura acima do pad rão na sala
xxxxx - 13/11/2015 08:43:24 - O dias 1 horas 15
minutos
Obs.: algumas informações foram ocultadas no
relatório, pois foram utilizados dados de um
monitoramento em ambiente de produção.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
10
Dicas de Projetos com
a API
Este capítulo não tem o intuito de ensinar a criar os projetos aqui
listados como dicas, e sim deixar que o leitor pense nas
possibilidades de criarprojetos com a experiência que adquiriu com
a API do Zabbix. Logicamente, alguns projetos não dependem
apenas da experiência com a API do Zabbix, como, por exemplo,
fazer dashboards, que requer o conhecimento de desenvolvimento
web e não é o foco desta obra.
10.1. Integração com software de
terceiros
Sistemas de gerenciamento de incidentes e configuração, tais
como OTRS e GLPI, são ideais para fazer uma integração com o
Zabbix. Pense nas possibilidades de automatizar uma abertura de
chamado através de um evento gerado por problema em uma
determinada trigger. E eu não estou falando de integração através
do envio de e-mail, que é limitado apenas à abertura de chamados.
Estou falando em automatizar o processo como um todo, desde a
abertura, passando por inclusão de informações até o fechamento
do chamado quando uma trigger voltar ao normal.
Esse tipo de integração requer conhecimento além da API do
Zabbix, pois exige a utilização de API ou webservices. Isso vai
depender do que o sistema tem disponível para utilização. Nos
exemplos que eu citei, o OTRS disponibiliza uma API para fazer
chamada aos métodos do sistema e o GLPI , um plug-in que
disponibiliza um webservice para fazer chamada aos métodos
disponíveis. Portanto, você deverá estudar os métodos que serão
utilizados na integração entre os sistemas.
Vou dar o exemplo aqui de como seria o projeto para fazer uma
integração com um sistema de gerenciamento de incidentes, com o
objetivo de abrir um ticket e fechá-lo automaticamente através da
mudança de estado de uma trigger.
Basicamente, a integração deverá funcionar a partir de um evento
ocorrido após uma trigger entrar em estado de problema. Quando
isso acontecer, uma ação deverá ser executada no Zabbix. Essa
ação será a execução de comando, que por sua vez fará a
chamada ao método da API ou webservice para abertura do ticket
no sistema (OTRS ou GLPI). Após a abertura do registro, temos a
opção de reconhecer o evento que foi gerado com o problema da
trigger. Nesse cenário, o código que utiliza a API ou o webservice
deverá conter a chamada à API do Zabbix para reconhecer o
evento e incluir a informação desejada nas observações desse
evento. Quando o estado da trigger voltar a ficar normalizado, a
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
execução do comando utilizará a chamada ao método da API ou
webservice para finalizar o ticket. Sua integração então estará
finalizada, com os registros sendo abertos e fechados
automaticamente. Isso é importante para você criar relatórios e
saber a quantidade de problemas que aconteceram em seu
ambiente automaticamente, separando os chamados gerados
através de ligações dos usuários da rede daqueles gerados
automaticamente com a integração.
Esse tipo de integração pode ser incrementado com as
chamadas de outros métodos dos sistemas. Exemplo: você pode
fazer uma verificação de problemas recorrentes do estado de uma
trigger e, em vez de abrir vários tickets, incrementar uma
informação no ticket e apenas final izá-lo quando determinada
trigger tiver com o seu estado normalizado após um período de
tempo estipulado.
Vimos que, nesses tipos de integração com software de terceiros,
o conhecimento deverá estar focado mais na API ou webservice do
sistema que será integrado do que com a própria API do Zabbix.
Dependendo do cenário, a integração irá ocorrer sem ao menos
fazer qualquer chamada à API do Zabbix, usando apenas
configurações da interface web para executar os comandos das
ações configuradas.
Você encontra uma amostra da integração Zabbix e GLPI na
seguinte URL:
https://github.com/janssenlima/zabbix-glpi
10.2. Geração de gráficos e relatórios
em PDF
Nos capítulos anteriores estudamos diversos métodos da API do
Zabbix que nos dão possibilidades de pensar na criação de vários
relatórios, seja gerencial contendo informações de problemas no
monitoramento ou gráficos dos recursos mais utilizados, entre
outras ideias. Vimos alguns exemplos de relatórios no Capítulo 9,
onde extraímos os dados e imprimimos somente a saída dos
dados.
Neste tópico, irei apresentar algumas bibliotecas com as quais
podemos trabalhar para gerar gráficos e montar relatórios em PDF.
As bibliotecas aqui apresentadas são na linguagem que foi
abordada no conteúdo do livro, ou seja, Python. Não cabe aqui
ensinar a utilizar a biblioteca, pois foge ao objetivo principal do livro.
10.2.1. Matplotlib
Matplotlib é uma biblioteca de plotagem 2D que produz figuras de
qualidade em uma variedade de formatos impressos e ambientes
interativos em várias plataformas. Você pode gerar gráficos,
histogramas, espectros de potência, gráficos de barras, gráficos de
dispersão etc. com apenas algumas linhas de código.
O site oficial do projeto é http://matplotlib.org . Nele você encontra
uma galeria com exemplos dos gráficos que podem ser feitos,
inclusive com os códigos desses exemplos. Também tem um
tutorial simples de como você instala essa biblioteca, disponível na
URL http://matplotlib.org/users/installing.html. Se você estiver
seguindo os pacotes que foram sugeridos nos capítulos iniciais,
provavelmente você terá instalado a biblioteca em seu ambiente.
Para testar se a biblioteca está instalada, abra o console do Python
e digite o seguinte código:
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
>>> irnport rnatplotlib
>>> print rnat p l otlib. ve r s i on
1. 1. l r c 2
Esses comandos também podem ser digitados no console do
Python disponível na IDE Spyder.
Exemplo de gráfico criado com a biblioteca Matplotlib:
-1>.5 -
- 3 -
-4 , • ' • '
,.1 .0 .-
-3 -2 -1 o 1 2 3 o
25 - • . -
1.5 -
20 - J..O -
15 -
~ ~
.0.5 .
O.O -
10 -
1
-
0 .5 -
s - -1 .0 -
o - . . _l .5 -' . • • . . . a b e d e -2 - 1 o 1
10.2.2. Bokeh
Bokeh é uma biblioteca de visualização interativa do Python que
tem como alvo os navegadores modernos para a apresentação de
suas imagens. Seu objetivo é fornecer construção elegante e
concisa de novos gráficos no estilo D3.js. Também oferece
interatividade de alto desempenho em conjuntos de dados muito
grandes ou streaming. Bokeh pode ajudar qualquer um que gostaria
de criar facilmente painéis interativos e aplicativos de dados.
O site oficial do projeto é http://bokeh.pydata.org/en/latest/. A
biblioteca Bokeh permite a atualização dinâmica dos dados a serem
exibidos através da implementação de um servidor que fica
responsável por reter os dados consumidos via API do Zabbix e
plotar o resultado em tempo real ou de acordo com o período de
tempo selecionado. Mesmo os gráficos estáticos podem ser
visualizados no seu navegador favorito. O grande diferencial dessa
biblioteca é que você pode configurar a visualização dos gráficos,
além de obter informações com a movimentação do mouse sobre
os pontos dos gráficos.
A instalação da biblioteca Bokeh pode ser feita utilizando a
ferramenta PIP com o seguinte comando:
pip install bokeh
Exemplo de gráfico criado com a biblioteca Bokeh:
10.2.3. ReportLab
Reportlab fornece o núcleo do produto comercial, Reportlab
Plus, que gera PDFs com o uso de poucas linhas de código de
maneira simples e rápida.
A versão open source é totalmente funcional, sendo possível a
geração de PDFs com tabelas, gráficos e documentos simples, tais
como relatórios e cartas comerciais.
Con sumindo a API do Zabbix com Python - Janssen dos Reis Lima
O site oficial do projeto open source é http://www.reportlab.com
/opensource.
A instalação do ReportLab pode ser feita utilizando o PIP com o
seguinte comando:
p ip inst al l reportlab
ReportLab é a biblioteca ideal para gerar relatórios
personalizados que não são disponibilizados pelo Zabbix. A seguir,
um simples exemplo de um relatório gerado com o ReportLab:
~orne do HOST : 3Com 2928 SFP lVIodulo 8
Qtde eventos período: 132
~10tÍYO
3Com 2928 SFP Modulo 8 is wul\'ailable by IC!'vlP
Operarional status was cba1111ed ou 3Com2928 SFP Modulo 8 inrerfai
Gig.abitEtheruetl/O 23
Operational staiUs was chru1ged on JCom 2928 SFP Modulo 8 interfa•
Gigabi1Etheme1l/O/ l9
Operational stams was cbanged on 3Com 2928 SFP Modulo 8 interfa
GigabitEtlleme1110/J 8
Operntional status was changed ou 3Com 2928 SFP ~loduJo 8 iuterfa
GigabitEthemetl /0121
Operariooal status was c;hanaed on 3Com 2928 SFP Modulo S interfa1
GigabitEtbemetl /0 114
Operarional s1arus was changed ou 3Com 2928 SFP Modulo 8 interfai
GigabitEthemet l/0/ 16
Operarional status was changed ou 3Com 2928 SFP Modulo 8 interfao
Gig3bitEthemet 110/11
Opera1ional srarus was cbanged on 3Com 2928 SFP Modulo 8 iuterfa
GigabitEthemet 110/ l O
Operational status was changed 011 3Cou1 2928 SFP Modulo S iJ1terfai
GigabitEthemer l/0/ 13
10.2.4. PyGal
PyGal é uma biblioteca de gráficos SVG dinâmicos. Possui vários
tipos de gráficos, como de barras, linha, pizza, radar, pirâmide, funil
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
etc. Possui características CSS com temas predefinidos. Essa
biblioteca permite incorporar os gráficos criados em páginas web, o
que pode perfeitamente ser aproveitado na interface web do
Zabbix.
id.1'e ite oficial do projeto é http://www.pygal.org/en/latest/. Nele
llii\Cê encontra diversos exemplos com códigos que poderão ser
u 1 1za os em seus projetos.
l8C30
A i stalação da biblioteca PyGal pode ser feita utilizando a
enta PIP com o seguinte comando:
i nst all pygal
-t-*E!mplo de gráfico criado com a biblioteca PyGal:
laca o
ll!CllO
l8C80
1<1cao
.ia e ao
. IE
• Firefox
• Chrome
• safari
• opera
0.8
Browser usage in February 2012 (in %'.
... e a.a u;.e 20 . e 24 .ll
10.3. Envio de relatórios por e-mail
Quem nunca precisou enviar um relatório para o e-mail de um
supervisor ou gerente?
Com a biblioteca smtplib você poderá automatizar todo o
processo de envio de seus relatórios gerados com o aprendizado
do conteúdo desta obra para ser entregue aos e-mails das pessoas
interessadas.
O site com a documentação oficial da biblioteca é
https://docs.python.org/2/library/smtplib.html. Uma rápida busca na
internet permite encontrar vários exemplos de códigos com uso
dessa biblioteca. Como não é o propósito desta obra, fica a cargo
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
do leitor procurar tais implementações.
Essa biblioteca já vem disponível por padrão na instalação do
Python. Para usá-la, basta fazer sua importação.
A biblioteca smtplib é utilizada para o envio de e-mails simples,
somente texto. Para enviar e-mails mais elaborados e também
arquivos em anexo, sugiro a utilização da biblioteca email
(https://docs.python.org/2. 7 /library/email.html). Como citei antes,
com uma rápida busca na internet você encontrará exemplos de
implementação também com a biblioteca email.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
11
Dicas Importantes
Para finalizar esta obra, acrescento neste capítulo quatro dicas
que julgo importantes para você começar a brincar com a API do
Zabbix.
11.1. Habilitando o Jog da biblioteca
zabbix-api
A primeira dica é habilitar o log da biblioteca zabbix_api para que
possamos obter informações de todo o processo de execução da
requisição. É sempre bom visualizarmos os dados que estamos
consumindo da API. Antes de imprimirmos ou formatarmos a saída
das requisições, podemos habilitar o log da biblioteca para
estudarmos melhor o que está se passando durante a requisição e
até mesmo visualizarmos os dados obtidos, mesmo que estejam no
formato JSON.
Por padrão, o log é desabilitado e apenas recebemos mensagens
de erros da requisição se algum parâmetro de um método for
inválido. Ou seja, por padrão, recebemos apenas as mensagens de
erros. O leitor deve ficar atento: estou comentando erros das
requisições. Não entrarei em detalhes sobre erros de sintaxe da
linguagem, que também podem aparecer no console do Python ou
no terminal do sistema. Podemos também habilitar o /og em nível
de informação e em nível de debug. Os códigos que identificam os
níveis de log na biblioteca são os seguintes:
)> O: nível padrão. Apenas mensagens de erros.
)> 10: nível de debug.
)> 20: nível de informação.
Para habilitarmos o nível de log, acrescentamos um parâmetro na
chamada da API onde passamos a URL de conexão. Veja o
exemplo a seguir:
zapi = ZabbixAPI{server="http: / /192.168. 0 .22
/zabbix", log_level=20 )
O exemplo mostra que foi passado um novo parâmetro, o
log_level, e informado o nível de /og, que neste caso foi o nível de
informação. Observe a saída após executar o código do tópico 3.3,
que utiliza o método host.get.
20: Set logging level to 20
INFO:zabbix_api.ZabbixAPI:20 : Set logging level
to 20
20: url: http://192.168.2.121 /zabbix
/api_jsonrpc.php
I NFO:zabbix_api.ZabbixAPI:2 0 : url :
htt p://192.168.2.121/zabbix/api_jsonrpc.php
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
20: Sendi ng: {"params" : {"password" : "zabbix",
"user" : "adrnin"}, "j sonrpc": "2. O", "me thod":
"user.login", " i d": O}
INFO:zabbix_api. ZabbixAPI:20 : Se nding:
{"params" : {"password" : "zabbix", " user":
"adrnin"} , "j sonrpc" : "2. O", "met h o d" :
"user.login", "id": O}
20: Response Code : 2 0 0
INFO:zabbix_ap i. ZabbixAPI:2 0 : Response Code: 200
20: Sending: {"params" : {"output": ["hostid",
"host"J}, "j sonrpc" : "2 . O", "met ho d":
"host.get", "auth":
"c44 12c20ee627891d4b3f092d0 69 56b2", " id": 1 }
INFO:za bbix_ api.ZabbixAPI:20: Sending:
{"params" : {"output": [ "hostid", "host" J } ,
"j sonrpc": "2 . O", "method": " host. get", "auth":
"c44 12c20ee627891d4b3f 092d0 6956b2", " id": 1 }
2 0 : Response Code : 2 0 0
INFO:za bbix_ api.ZabbixAPI : 20: Response Code: 200
10084 Zabbix server
101 0 9 TesteJanssen
10142 - nmap
10159 - CursoAPI
10160 - CursoAPIRemover
1010 6
1010 7
Cable Modem
Cliente
Repare as diferenças ao ativarmos o nível de debug:
20: Set l ogging level to 10
I NFO:zabbi x_api.ZabbixAPI:20 : Set logging level
to 10
20: url: http:/( 192.168.2.121/zabbix
/api_jsonrpc. p hp
I NFO: zabbi x_api.ZabbixAPI:20 : url:
http: f /192.168 .2.121 / z abbix/api_ jsonrpc.php
10: Trying t-0 login with
'adrnin' :'md5 (5 fcelb3e34b520a fe f fb37ce 08c7cd 66)'
DEBUG : zabbix_api.ZabbixAPI:lO: Trying to l ogin
with
' a drnin' :'md5(5fcelb3e34b520afeffb37ce08c7cd 66)'
10: json_obj: {'params' : { ' password': 'zabbix',
'user': 'adrnin' }, 'jsonrpc': '2.0', 'method':
'user.login', 'id': O}
DEBUG : zabbix_api.ZabbixAPI:lO: json_obj:
{ ' params': { 'password ' : 'zabbix', 'user' :
'adrnin' }, 'jsonrpc': '2. 0 ', 'me t hod':
'user . login', 'id': O}
20: Send ing : {"params": {"password": "zabbix" ,
"user": "adrnin"}, "j sonrpc": "2. O", "method":
"user. login", "id": O}
I NFO: zabbix_api. ZabbixAPI:20 : Sending :
{"params": {"password": "zabbix", "user" :
"adrnin"}, " j sonrpc": "2. O", "me t hod":
"user . login", "id": O}
10: Send ing headers: { 'Content-Type':
'application/ j son- rpc', 'User-Agent ' :
' p ython/ zabbix_api '}
DEBUG : zabbix_api.ZabbixAPI:lO: Sending headers:
{'Content- Type': 'application/json-rpc', 'User-
Agent': 'python/zabbix_api' }
20: Response Code : 200
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
INFO:za bbix_ a p i.ZabbixAPI: 20 : Response Code: 2 0 0
10 : Response Body: {u'jsonrpc': u ' 2 . 0 ',
u 'result ' : u'474e2 f 3 c 6d83c3f c48a6fd 6 l a92 f 69e0',
u ' id' : O}
DEBUG:zabb ix_api . Zabbi xAPI:lO : Response Bod y :
{u' j sonrpc': u '2 . 0 ', u'resu lt ':
u '474e2f3c6d83c3fc48a6fd 6la92f69e0 ', u'id': O}
10 : j son _ obj : { ' p arams' : { 'output' : [ 'hostid',
'host 'J}, ' j sonrpc' : ' 2.0', ' met ho d ':
'host .get', ' a uth':
u ' 47 4e2f3c6d83c3fc48a6f d 6la92f69e0 ', 'id ' : 1}
DEBUG:zabb ix_api . Zabbi xAPI:lO : json_obj:
{ 'pa rams' :{'output': [ 'hostid', 'host' J },
'jsonrp c ' : '2 . 0 ', ' method': ' host.get ', 'au th':
u ' 4 7 4e2f3c6d 83c3fc48a6f d 6la92f69e0 ', 'id ' : 1}
2 0 : Send i ng: {"pa rams" : {"out put ": [ "hostid ",
"host "J}, " j sonrpc" : "2. O", "meth od ":
"host . get", " a uth" :
"474e2 f 3c6d 83c3f c48a 6f d6la 92 f 69e0", " i d": 1 }
INFO:za bbix_ a p i.ZabbixAPI: 20: Sending:
{"pa rams" : {"outp u t ": ["hostid", "host" J },
"j sonrp c " : "2 . O", "method": " host. get ", " a u th":
"474e2f3c6d 83c3f c48a 6f d6la 92 f 69e0", " i d": 1 }
10 : Send i ng headers : {'Cont ent- Type ':
'appli cation/ j son-rpc', 'User- Agent ':
'pyth on/ z a bbix_ api' }
DEBUG:zabbix_ap i. Zabbi xAPI:lO : Send ing headers:
{ 'Conte nt- Type' : 'appl i cation/ json- rpc', 'User-
Agent ' : ' p ython/ zabbix_ a p i'}
2 0 : Respo nse Code: 2 0 0
INFO:za bbix_ api.ZabbixAPI: 20: Response Code: 2 0 0
10 : Response Bod y: {u' j sonrpc': u '2 . 0 ',
u'resu l t ': [ {u' host ': u'Zab:Oix server',
u' hostid': u '10084'}, {u' host ' : u'TesteJ a nssen',
u' hostid': u 'l0109'}, {u'host ' : u' nmap',
u' hostid ': u '101 42'}, {u'host ' : u' Cur50API ',
u' hostid': u '101 59'}, {u'host ' :
u'CursoAPIRemover', u'hostid': u '10160 ' },
{u'host ' : u'Cab le Mo d em', u' hosti dr: u '10106' },
{u' h ©st' : u' Cl iente', u' hostid' : u' 1010 7'} J,
u'id' : 1 }
DEBUG : zabbix_api.ZabbixAPI : l O: Response Bod y:
{u' j sonrpc' : u'2.0', u 'result ' : [{u'host':
u'Zabbi x server', u 'host id' : u' 10084' } ,
{u 'host' : u'Test eJa nssen', u 'hostid ' : u' 1010 9' } ,
{u'host' : u'runap', u'hostid ': ur101 42' },
{u'host' : u'CursoAPI ', u'host i d ' : u '10159'},
{u'host' : u'CursoAPI Remover', u'hostid' :
u' 10160 ' } , {u'host ': u 'Ca b le Mod em', u 'hostid ' :
u' 1010 6' } , {u'host': u 'Client e', u'hostid' :
u' 1010 7' }], u 'id ' : 1}
100 84 Zabbix server
1 0109 TesteJa nssen
10142 nmap
10159 CursoAPI
101 60 CursoAPIRe move r
10106 Cable Modem
10107 Cliente
O nível de debug é utilizado para uma verificação mais criteriosa
do retorno da requisição.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
11.2. Timeout das requisições
Assim como é possível alterarmos o nível de log, também
podemos ajustar o tempo de resposta das requisições. O tempo
padrão de resposta das requisições que a biblioteca zabbix-api
utiliza é de dez segundos. Dependendo do ambiente, pode
acontecer de requisições remotas ultrapassarem o tempo padrão e
o cliente não obter a resposta do servidor. Quando isso acontecer,
você receberá a seguinte mensagem de erro da API:
APITimeout: HTTP read timeout
Para resolver esse problema, o parâmetro timeout deverá ser
ajustado conforme o exemplo a seguir:
zapi = ZabbixAPI(server="http : //1 92 . 1 68.0 . 22
/ zabbix", timeout= 20 )
O parâmetro timeout foi ajustado para vinte segundos. Em
ambientes onde as requisições forem executadas remotamente, o
leitor deverá ajustar um tempo satisfatório para receber as
respostas e não abusar muito desse parâmetro colocando valores
muito altos.
11.3. Procure threads em fóruns e listas
de discussão
Mesmo que você não participe ativamente de fóruns e listas de
discussão respondendo dúvidas de outros usuários, é muito
importante que você leia todas as threads possíveis sobre API. Por
diversas vezes eu estava querendo alguma ideia de relatório,
listagem ou automação com a API e eu tirei como desafio as ideias
postadas nos fóruns. As dúvidas não são poucas e você encontra
muitos desafios para começar a praticar o consumo da API do
Zabbix.
Para discutir sobre API , eu sugiro o fórum oficial do Zabbix -
http://www.zabbix.com/forum. Se você for mais underground e
quiser ir mais além, acesse o IRC Channel #zabbix na rede
FreeNode http://webchat.freenode.net/?channels=#zabbix.
Nesses canais você irá encontrar conteúdo sobre API do Zabbix em
inglês. Raras vezes aparecem threads em outros idiomas. Espero
que com este livro apareçam mais pessoas interessadas em
discutir API em fóruns e listas em português.
11.4. Leia a documentação oficial
Em nenhum outro lugar do mundo você encontrará mais
conteúdo sobre a API do Zabbix do que na própria documentação
oficial. A API do Zabbix é bem documentada e você encontra as
propriedades e os parâmetros dos métodos com suas devidas
explicações em detalhes que não deixam dúvidas quanto à sua
correta utilização.
Consumindo a API do Zabbix com Python - Janssen dos Reis Lima
Referências
Bibliográficas
DATA SCIENCE CENTRAL. Python Visualization Libraries List.
June 22, 2015. Disponível em: <http://www.datasciencecentral.com
/profiles/blogs/opensource-python-visualization-libraries>. Acesso
em: 15 dez. 2015
EPOCHCONVERTER. Epoch & Unix Timestamp Conversion
Tools. Disponível em: <http://www.epochconverter.com/>. Acesso
em: 15 dez. 2015.
JSON. lntroducing JSON. Disponível em: <http://json.org>. Acesso
em: 15 dez. 2015.
LIMA, L. Como ordenar um dicionário em Python. Blog Estudar
Computação, 03 ago. 2011 . Disponível em:
<http ://www.estudarcomputacao.com/2011 /08/como-orde nar-um-
dicionario-em-python. htm I>. Acesso em: 15 dez. 2015.
PYTHON.ORG. The Python Tutorial. Disponível em:
<https://docs.python.org/2/tutorial/>. Acesso em: 15 dez. 2015.
REPORTLAB. Reportlab open-source PDF Toolkit. 2015.
Disponível em: <http://www.reportlab.com/opensource/>. Acesso
em: 15 dez. 2015.
ZABBIX. Zabbix Documentation 2.4. Disponível em:
<https://www.zabbix.com/documentation/2.4/manual/api>. Acesso
em: 15 dez. 2015.
ZABBIX.ORG. Zabbix API Libraries. Disponível em:
<http://zabbix.org/wiki/Docs/api/libraries>. Acesso em: 15 dez.
2015.
9818
9820
9822
9823
9825
9827
9828
9830
9832
9833
9835
9836
9838
9840
9841
9843
9845
9846
9848
9849
9851
9852
9854
9856
9857
9859
9861
9862
9864
9865
9867
9869
9870
9872
9873
9875
9877
9878
9880
9881
9883
9885
9886
9887
9888
9889
9891
9893
9894
9896
9898
9899
9901
9902
9904
9906
9907
9909
9910
9912
9914
9916
9917
9919
9920
9922
9923
9925
9927
9928
9930
9931
9933
9935
9936
9938
9939
9941
9943
9944
9946
9947
9949
9951
9952
9954
9955
9957
9959
9960
9962
9964
9965
9967
9968
9970
9972
9973
9975
9976
9978
9980