5 Módulos carregáveis

5.1 Visão geral

Os módulos carregáveis são uma opção para estender as funcionalidades do Zabbix com o foco em alta performance.

Existem outras formas de se estender as funcionalidades do Zabbix:

Todas estas formas funcionam muito bem, mas tem um problema intrínseco, normalmente conhecido como 'fork()'. O Zabbix precisa direcionar um de seus processos para gerenciar métrica que se quer obter, toda vez que é necessário coleta-la, e isso não é uma boa opção para performance. Normalmente isso não é um grande problema, mas se formos fazer uma monitoração séria de sistemas críticos, com uma grande quantidade de parâmetros ou scripts muito complexos / longos de se executar... isso deixa de ser verdade.

O Zabbix 2.2 inovou ao adicionar o suporte a módulos carregáveis para estender as funcionalidades do Zabbix Agent, Server e Proxy sem perder performance.

Um módulo carregável é basicamente uma biblioteca compartilhada utilizada por um processo do Zabbix e carregada junto com o mesmo. A biblioteca precisará ter determinadas funções para que o Zabbix possa detecta-las no arquivo e saber como trabalhar com ela.

Os módulos carregáveis tem uma grande quantidade de benefícios. O aumento de performance e a habilidade de se aplicar qualquer lógica é muito importante, mas talvez o maior ganho seja a habilidade de desenvolver, usar e compartilhar os módulos. Isso auxilia nos processos de manutenção livre de problemas e auxilia a entregar novas funcionalidades de forma fácil e independente do código base do Zabbix.

5.2 API de módulos

Para que uma biblioteca compartilhada possa ser tratada como um módulo do Zabbix, é muito importante que ela implemente e exporte determinadas funções. Atualmente são cinco as funções da API de módulos do Zabbix, sendo duas obrigatórias e as outras três opcionais.

5.2.1 Interfaces obrigatórias

As duas funções obrigatórias são: zbx_module_api_version() e zbx_module_init():

int zbx_module_api_version(void);

Esta função deve retornar a versão da API implementada no móduo, atualmente existe somente uma versão: ZBX_MODULE_API_VERSION_ONE (definida com o valor 1), então esta função deverá retornar esta constante.

int zbx_module_init(void);

Esta função é responsável por fazer a inicialização do módulo (se existir). Se for concluída com sucesso deverá retornar: ZBX_MODULE_OK. Em qualquer outra situação, deverá retornar: ZBX_MODULE_FAIL.

5.2.2 Interfaces opcionais

Existem três funções opcionais: zbx_module_item_list(), zbx_module_item_timeout() e zbx_module_uninit():

ZBX_METRIC  *zbx_module_item_list(void);

Esta função deverá retornar uma lista de itens suportados no módulo. Cada item é definido como uma estrutura 'ZBX_METRIC', veja a seção a seguir para detalhes. Uma lista ZBX_METRIC deverá possuir uma estrutura onde o último campo key tem o valor NULL.

void    zbx_module_item_timeout(int timeout);

Esta função é utilizada pelo Zabbix para especificar as configurações de 'timeout' no arquivo de configuração do Zabbix que o módulo deverá obedecer. O tempo de espera é definido em segundos.

int zbx_module_uninit(void);

Esta função executa a liberação de recursos, tal qual liberar recursos alocados, fechar descritores de arquivo, etc..

Todas as funções são chamadas durante a inicialização do Zabbix, quando o módulo é carregado, com exceção da função zbx_module_uninit(), que será chamada quando o Zabbix estiver sendo terminado.

5.2.3 Definindo itens

Cada item é definido com uma estrutura 'ZBX_METRIC':

typedef struct
       {
           char        *key;
           unsigned    flags;
           int     (*function)();
           char        *test_param;
       }
       ZBX_METRIC;

Nesta estrutura:

  • key - a chave do item (ex. "dummy.random")
  • flags - pode ser 'CF_HAVEPARAMS' ou '0' (dependendo do item aceitar parâmetros ou não)
  • function - é uma função em C que implementa o item (ex. "zbx_module_dummy_random")
  • test_param - é ua lista de parâmetros para ser utilizada quando o Zabbix Agent for inicializado usando a marca "-p" (ex "1,1000", pode ser 'NULL'). Uma exemplo de definição usando esta estrutura pode ser:
static ZBX_METRIC keys[] =
       {
           { "dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random, "1,1000" },
           { NULL }
       }

Cada função que implementa um item deve aceitar dois ponteiros, o primeiro com o tipo AGENT_REQUEST, o segundo com o tipo AGENT_RESULT:

int zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           ...
       
           SET_UI64_RESULT(result, from + rand() % (to - from + 1));
       
           return SYSINFO_RET_OK;
       }

Estas funções deverão retornar 'SYSINFO_RET_OK', se o valor foi obtido com sucesso. Qualquer outra situação o retorno deverá ser 'SYSINFO_RET_FAIL'. Veja o exemplo do módulo "dummy" a seguir para detalhes sobre como obter informações sobre o AGENT_REQUEST e como configurar o AGENT_RESULT.

5.2.4 Construindo os módulos

Os módulos precisam ser construídos internamente na árvore do código fonte do Zabbix, pois o módulo depende de algumas estruturas de dados que são definidas nos cabeçalhos do Zabbix.

O cabeçalho mais importante para os módulos carregáveis é include/module.h, que define as estruturas de dados. Outro cabeçalho útil é include/sysinc.h, que faz a inclusão dos cabeçalhos de sistema que serão necessários, que por sua vez auxilia o include/module.h a funcionar adequadamente.

Para que include/module.h e include/sysinc.h sejam incluídos, o comando ./configure (sem parâmetros) deverá ser executado no diretório raiz dos fontes do Zabbix. Isso irá criar o arquivo include/config.h, com as dependências do include/sysinc.h. (Se você tiver obtido o código fonte do Zabbix a partir do "Subversion repository", o script ./configure não existirá e o comando ./bootstrap.sh deverá ser executado primeiro para gera-lo.)

Com esta informação em mente, tudo está pronto para criar o módulo. O módulo deverá incluir sysinc.h e module.h, e o script de criação se certificará que estes dois arquivos estão disponíveis no path. Veja o exemplo do módulo "dummy" a seguir para maiores detalhes.

Outro cabeçalho útil é o include/log.h, que define a função zabbix_log(), que poderá ser utilizada com o propósito de registro e debug.

5.3 Parâmetros de configuração

O Zabbix Agent, Server e Proxy suportam dois parâmetros para lidar com os módulos:

  • LoadModulePath – caminho completo para a localização dos módulos carregáveis
  • LoadModule – módulo(s) para ser carregado durante a inicialização. Os módulos deverão estar localizados no diretório definido em LoadModulePath. Também é permitida a inclusão de múltiplos módulos.

Por exemplo, para estender o Zabbix Agent nós podemos adicionar os parâmetros a seguir:

LoadModulePath=/usr/local/lib/zabbix/agent/
       LoadModule=mariadb.so
       LoadModule=apache.so
       LoadModule=kernel.so
       LoadModule=dummy.so

Quando o agente for inicializado ele irá carregar os módulos mariadb.so, apache.so, kernel.so and dummy.so a partir do diretório /usr/local/lib/zabbix/agent. Se um dos módulos estiver ausente, ou não tiver com o permissionamento correto, ou não for um 'Módulo Zabbix' a carga do agente irá falhar.

5.4 Configuração na interface web

Os módulos carregáveis são suportados pelo Zabbix Agent, Server e Proxy. Portanto, o tipo do item depende de onde foi carregado. Se o módulo tiver sido carregado no agente, o tipo deverá ser "Agente Zabbix" ou "Agente Zabbix (ativo)". Se o módulo tiver sido carregado no Server ou Proxy, o tipo do item deverá ser "Verificação simples".

5.5 Módulo Dummy

O código fonte do Zabbix 2.2 inclui um exemplo de módulo desenvolvido em C. O módulo está localizado em src/modules/dummy:

alex@alex:~trunk/src/modules/dummy$ ls -l
       -rw-rw-r-- 1 alex alex 9019 Apr 24 17:54 dummy.c
       -rw-rw-r-- 1 alex alex   67 Apr 24 17:54 Makefile
       -rw-rw-r-- 1 alex alex  245 Apr 24 17:54 README

O módulo é bem documentado e pode ser utilizado como um modelo para que você construa os seus próprios módulos.

Após executar o ./configure no diretório raiz dos fontes do Zabbix, conforme informado anteriormente, apenas execute o comando make para compilar o dummy.so.

/*
       ** Zabbix
       ** Copyright (C) 2001-2013 Zabbix SIA
       **
       ** This program is free software; you can redistribute it and/or modify
       ** it under the terms of the GNU General Public License as published by
       ** the Free Software Foundation; either version 2 of the License, or
       ** (at your option) any later version.
       **
       ** This program is distributed in the hope that it will be useful,
       ** but WITHOUT ANY WARRANTY; without even the implied warranty of
       ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       ** GNU General Public License for more details.
       **
       ** You should have received a copy of the GNU General Public License
       ** along with this program; if not, write to the Free Software
       ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
       ** MA  02110-1301, USA.
       **/
       
       #include "sysinc.h"
       #include "module.h"
       
       /* the variable keeps timeout setting for item processing */
       static int    item_timeout = 0;
       
       int    zbx_module_dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result);
       int    zbx_module_dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result);
       int    zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result);
       
       static ZBX_METRIC keys[] =
       /* KEY               FLAG           FUNCTION                TEST PARAMETERS */
       {
           {"dummy.ping",   0,             zbx_module_dummy_ping,  NULL},
           {"dummy.echo",   CF_HAVEPARAMS, zbx_module_dummy_echo,  "a message"},
           {"dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random,"1,1000"},
           {NULL}
       };
       
       /******************************************************************************
       *                                                                            *
       * Function: zbx_module_api_version                                           *
       *                                                                            *
       * Purpose: returns version number of the module interface                    *
       *                                                                            *
       * Return value: ZBX_MODULE_API_VERSION_ONE - the only version supported by   *
       *               Zabbix currently                                             *
       *                                                                            *
       ******************************************************************************/
       int    zbx_module_api_version()
       {
           return ZBX_MODULE_API_VERSION_ONE;
       }
       
       /******************************************************************************
       *                                                                            *
       * Function: zbx_module_item_timeout                                          *
       *                                                                            *
       * Purpose: set timeout value for processing of items                         *
       *                                                                            *
       * Parameters: timeout - timeout in seconds, 0 - no timeout set               *
       *                                                                            *
       ******************************************************************************/
       void    zbx_module_item_timeout(int timeout)
       {
           item_timeout = timeout;
       }
       
       /******************************************************************************
       *                                                                            *
       * Function: zbx_module_item_list                                             *
       *                                                                            *
       * Purpose: returns list of item keys supported by the module                 *
       *                                                                            *
       * Return value: list of item keys                                            *
       *                                                                            *
       ******************************************************************************/
       ZBX_METRIC    *zbx_module_item_list()
       {
           return keys;
       }
       
       int    zbx_module_dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           SET_UI64_RESULT(result, 1);
       
           return SYSINFO_RET_OK;
       }
       
       int    zbx_module_dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           char    *param;
       
           if (1 != request→nparam)
           {
               /* set optional error message */
               SET_MSG_RESULT(result, strdup("Invalid number of parameters"));
               return SYSINFO_RET_FAIL;
           }
       
           param = get_rparam(request, 0);
       
           SET_STR_RESULT(result, strdup(param));
       
           return SYSINFO_RET_OK;
       }
       
       /******************************************************************************
       *                                                                            *
       * Function: zbx_module_dummy_random                                          *
       *                                                                            *
       * Purpose: a main entry point for processing of an item                      *
       *                                                                            *
       * Parameters: request - structure that contains item key and parameters      *
       *              request→key - item key without parameters                    *
       *              request→nparam - number of parameters                        *
       *              request→timeout - processing should not take longer than     *
       *                                 this number of seconds                     *
       *              request→params[N-1] - pointers to item key parameters        *
       *                                                                            *
       *             result - structure that will contain result                    *
       *                                                                            *
       * Return value: SYSINFO_RET_FAIL - function failed, item will be marked      *
       *                                 as not supported by zabbix                 *
       *               SYSINFO_RET_OK - success                                     *
       *                                                                            *
       * Comment: get_rparam(request, N-1) can be used to get a pointer to the Nth  *
       *          parameter starting from 0 (first parameter). Make sure it exists  *
       *          by checking value of request→nparam.                             *
       *                                                                            *
       ******************************************************************************/
       int    zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           char  *param1, *param2;
           int   from, to;
       
           if (request→nparam != 2)
           {
               /* set optional error message */
               SET_MSG_RESULT(result, strdup("Invalid number of parameters"));
               return SYSINFO_RET_FAIL;
           }
       
           param1 = get_rparam(request, 0);
           param2 = get_rparam(request, 1);
       
           /* there is no strict validation of parameters for simplicity sake */
           from = atoi(param1);
           to = atoi(param2);
       
           if (from > to)
           {
               SET_MSG_RESULT(result, strdup("Incorrect range given"));
               return SYSINFO_RET_FAIL;
           }
       
           SET_UI64_RESULT(result, from + rand() % (to - from + 1));
       
           return SYSINFO_RET_OK;
       }
       
       /******************************************************************************
       *                                                                            *
       * Function: zbx_module_init                                                  *
       *                                                                            *
       * Purpose: the function is called on agent startup                           *
       *          It should be used to call any initialization routines             *
       *                                                                            *
       * Return value: ZBX_MODULE_OK - success                                      *
       *               ZBX_MODULE_FAIL - module initialization failed               *
       *                                                                            *
       * Comment: the module won't be loaded in case of ZBX_MODULE_FAIL             *
       *                                                                            *
       ******************************************************************************/
       int    zbx_module_init()
       {
           /* initialization for dummy.random */
           srand(time(NULL));
       
           return ZBX_MODULE_OK;
       }
       
       /******************************************************************************
       *                                                                            *
       * Function: zbx_module_uninit                                                *
       *                                                                            *
       * Purpose: the function is called on agent shutdown                          *
       *          It should be used to cleanup used resources if there are any      *
       *                                                                            *
       * Return value: ZBX_MODULE_OK - success                                      *
       *               ZBX_MODULE_FAIL - function failed                            *
       *                                                                            *
       ******************************************************************************/
       int    zbx_module_uninit()
       {
           return ZBX_MODULE_OK;
       }

Este módulo exporta três novos itens:

  • dummy.ping - sempre retorna '1'
  • dummy.echo[param1] - retorna o primeiro parâmetro que for informado, por exemplo, dummy.echo[ABC] retornará: ABC
  • dummy.random[param1, param2] - retorna um número randômico dentro do range definido em param1-param2, por exemplo, dummy.random[1,1000000]

5.6 Limitações

O suporte para módulos carregáveis foi implementado apenas na plataforma UNIX. Isso significa que não irão funcionar em Agentes para Windows.

Em alguns casos o módulo pode precisar ler parâmetros de configuração do zabbix_agentd.conf. Isso ainda não é fornecido pela API, se você precisar obter tais parâmetros você deverá implementar a análise do arquivo de configurações.

5.7 Limitations

Support of loadable modules is implemented for the Unix platform only. It means that it does not work for Windows agents.

In some cases a module may need to read module-related configuration parameters from zabbix_agentd.conf. It is not supported currently. If you need your module to use some configuration parameters you should probably implement parsing of a module-specific configuration file.