Начало работы с Zabbix API

Что такое Zabbix API

Как правило у вас есть только один путь для манипуляций, настройки и создания объектов в Zabbix - через PHP веб интерфейс. Это очень удобно, однако только до того момента пока вы не решите создать что то особенное: создать пакетный скрипт добавления/обновления, или пользовательский инструмент мониторинга, или что то еще, что не Zabbix GUI интерфейс не предоставляет по умолчанию.

Вот тогда Zabbix API и приходит на помощь. Он позволяет создавать, обновлять и получать объекты Zabbix(например, узлы сети, элементы данных, графики и др.) через протокол JSON RPC и делать все, что вам нравится (если у вас есть аккаунт, уполномоченный на эти действия, конечно).

Zabbix API был введен в версии 1.8 и активно разрабатывается до сих пор. В некоторых местах, функциональность все еще ограничена, но он обещает стать гораздо шире после выпуска Zabbix 2.0.

Пример сессии

Для быстрого обзора, взгляните на пример сессии Zabbix API или читайте ниже для более подробного объяснения.

Использование JSON RPC

Если вы не знакомы с JSON RPC, не бойтесь, все сложности отмечены ниже. Весь рабочий процесс заключается в нескольких шагах:

  1. Подготовка объекта JSON, который описывает то что вы хотите сделать (создать узел сети, получить график, обновить элемент данных и т.д.);
  2. Отправка этого объекта используя метод POST на http://example.com/zabbix/api_jsonrpc.php, где http://example.com/zabbix/ это адрес вашего веб-интерфейса Zabbix;
  3. Получитьответ с желаемыми данными в формате JSON.

В большинстве случаев вы будете делать это из скриптов, с помощью инструментов скриптового язык, но, конечно, вы можете отправлять запросы «вручную», используя любой из желаемых инструментов JSON-RPC.

В самом деле, правильно! Все, что вам нужно знать сейчас, это способ аутентификации для этого, и то, какой формат JSON является ожидаемым для Zabbix.

Базовый формат запроса

Упрощенный запрос JSON в Zabbix API выглядит следующим образом:

{
          "jsonrpc": "2.0",
          "method": "method.name",
          "params": {
             "param_1_name": "param_1_value",
             "param_2_name": "param_2_value"
          },
          "id": 1,
          "auth": "159121b60d19a9b4b55d49e30cf12b81"
       }

Давайте взглянем на каждую строку:

  • "jsonrpc": "2.0" - это стандартный параметр JSON PRC идентификации версии протокола. Он не будет меняться для всех ваших запросов;
  • "method": "method.name" - этот параметр определяет фактически выполняемую операцию. Общие примеры: "host.create", "item.update" и так далее;
  • "params" - здесь вы передаете объект JSON с параметрами требуемыми для указанного метода. Если вы хотите создать элемент данных, например, параметры "name" и "key_" будут обязательными. Возможные параметры для каждого метода (и сами методы) описываются в документации Zabbix API;
  • "id": 1 - это поле может быть использовано, чтобы связать каждый запрос JSON с ответом. Ответ будет иметь такой же "id" как и указанный в запросе. Не обязательно должен быть уникальным или последовательным;
  • "auth": "159121b60d19a9b4b55d49e30cf12b81" - Это ключ аутентификации для идентификации пользователя для доступа к API. Смотрите раздел Аутентификация для получения более подробной информации.

Аутентификация

И так, теперь мы знаем как использовать API. Давайте взглянем на метод host.create и создадим новый узел сети. Давайте отправим запрос:

{
          "jsonrpc": "2.0",
          "method": "host.create",
          "params": {
             "host": "My first host name",
             "ip": "192.168.3.1",
             "port": 10050,
             "useip": 1,
             "groups": [
                {
                   "groupid": 50
                }
             ]
          },
          "id": 1
       }

Zabbix ответит:

{
           "jsonrpc": "2.0",
           "error": {
               "code": -32602,
               "message": "Invalid params.",
               "data": "Not authorized"
           },
           "id": 1
       }

Что произошло? Конечно, не случайный человек может отправить запрос Zabbix на получение информации или для изменения чего-нибудь. Вот зачем вам нужно проходить аутентификацию для того, чтобы что-нибудь сделать.

Хорошее время отметить несколько моментов:

В случае любой ошибки, в результате вы получите параметр "error":

  • Параметр "code" будет всегда равен -32602 (это код ошибки JSON для ошибочных параметров);
  • "message" отражает ту же информацию что и вернул нам "code" и не будет сильно отличаться;
  • "data" будет описывать, что действительно пошло не так.

В случае успеха, вы получите параметрo "result" вместо "error" (как вы увидите далее).

И так, как получить аутентификацию? Вам потребуется отправить запрос, вызвав метод "user.login" и указав параметрами "user" и "password".

{
          "jsonrpc": "2.0",
          "method": "user.login",
          "params": {
             "user": "Admin",
             "password": "zabbix"
          },
          "id": 1
       }

"Admin/zabbix" является учетной записью в Zabbix по умолчанию, но вы уже вероятно изменили пароль Админа. Не так ли?

Таким образом, мы получим ответ:

{
           "jsonrpc": "2.0",
           "error": {
               "code": -32602,
               "message": "Invalid params.",
               "data": "No API access"
           },
           "id": 1
       }

Опять, отказ. Что случилось на этот раз? Дело в том, что в Zabbix 1.8 пользователи, которые не находятся в группе с "Доступом к API" не имеют доступа к Zabbix API по умолчанию. Для того чтобы использовать API для нужного пользователя, вам нужно установить "Доступ к API" в "Активирован" для группы пользователей этого пользователя или поместить пользователя в группу с предустановленным "API доступом".

Теперь, когда ваш пользователь является членом группы пользователей с включенным "Доступ к API", попробуем отправить такой же запрос снова:

{
          "jsonrpc": "2.0",
          "method": "user.login",
          "params": {
             "user": "Admin",
             "password": "zabbix"
          },
          "id":1
       }

Ответ:

{
           "jsonrpc": "2.0",
           "result": "7cd4e1f5ebb27236e820db4faebc1769",
           "id": 1
       }

Ура! Аутентификация успешна! Что теперь? Теперь мы можем использовать хэш возвращенный в параметре "result", как доказательство наших прав, путем включения в каждый создаваемый запрос API, параметром "auth".

Примеры использования и общие параметры

Теперь, когда вы авторизовались можно пойти дальше и сделать что-нибудь. Прежде всего, давайте попробуем получить какую-нибудь информацию.

Получение списка групп узлов сети

Вот простой запрос на получение всех доступных групп узлов сети с сортировкой по имени

{
          "jsonrpc": "2.0",
          "method": "hostgroup.get",
          "params": {
             "output": "extend",
             "sortfield": "name"
          },
          "id": 1,
          "auth": "7cd4e1f5ebb27236e820db4faebc1769"
       }

Обратите внимание, что "method" содержит "hostgroup.get", фактическую процедуру которую мы выполняем, и "params" содержащий дополнительные опции.

"sortfield", как вы можете догадаться, позволяет сортировать результат, который вы получаете по выбранному полю.

"output":"extend" означает, что вы хотите получить всю доступную информацию о каждой группе. Это, в некотором роде похоже на "SELECT *" в SQL. Возможными вариантами "output" могут быть:

  • "extend" - получить всю информацию;
  • "shorten" - получить только id объектов;
  • "refer" - получить id объекта и так же id связанных объектов;
  • список полей, таких как ["groupid", "name"] - получить поля только из списка.

Список полей доступен только для get методов Alert, DCheck, Host, DService, Screenitem, Template и Trigger.

И не забывайте о хэше "auth", который вы получили используя "user.login".

Ответ на данный запрос может выглядеть следующим образом::

{
           "jsonrpc": "2.0",
           "result": [
               {
                   "groupid": "5",
                   "name": "Discovered hosts",
                   "internal": "1"
               },
               {
                   "groupid": "2",
                   "name": "Linux servers",
                   "internal": "0"
               },
               {
                   "groupid": "1",
                   "name": "Templates",
                   "internal": "0"
               },
               {
                   "groupid": "3",
                   "name": "Windows servers",
                   "internal": "0"
               },
               {
                   "groupid": "4",
                   "name": "Zabbix servers",
                   "internal": "0"
               }
           ],
           "id": 1
       }

Это стандартные группы, созданные при первичной настройке Zabbix. Обратите внимание на поле "groupid", поля "XXXXid" уникальные идентификаторы системы, которые будут использоваться для адресации на объект в других запросах. Смотрите следующий раздел для объяснений.

Создание узла сети

Мы получили группы узлов сети, теперь попробуем что-нибудь создать. Попробуем создать узел сети, который будет находиться в группе узлов сети "Linux servers" и "Zabbix servers". Запрос будет выглядеть следующим образом:

{
          "jsonrpc": "2.0",
          "method": "host.create",
          "params": {
             "host": "My new fancy host that I have created using API",
             "ip": "192.168.3.1",
             "port": 10050,
             "useip": 1,
             "groups": [
                {
                   "groupid": 2
                },
                {
                   "groupid": 4
                }
             ]
          },
          "id": 1,
          "auth": "7cd4e1f5ebb27236e820db4faebc1769"
       }

Обратите внимание, мы используем поля "groupid" полученные ранее, для связки с группами в которые мы хотим, чтобы входил наш узел сети. Мы, говорим, что хотим чтобы узел сети был в группах с id 2 (Linux servers) и 4 (Zabbix servers). Таким способом, вы будете работать со всеми сопутствующими объектами.

Если все пойдет верно, вы получите ответ:

{
           "jsonrpc": "2.0",
           "result": {
               "hostids": [
                   "10051"
               ]
           },
           "id": 1
       }

Список "hostids" содержит элементы id, которые мы только что создали. В нашем случае, мы создавали только один узел сети и получили ID - 10051. Вы можете его использовать в будущих запросах.

Обновление элемента данных

Конечно, если вы можете создавать что-либо, вы должны иметь возможность обновлять или удалять. И для вас, чтобы попробовать и обновить элемент данных, я создал элемент данных с описанием "agent.ping" в созданном ранее "Моем новом придуманном узле сети, который я создал с помощью API", так что можно поиграть с ним. Во-первых, давайте посмотрим на это:

Запрос:

{
          "jsonrpc": "2.0",
          "method": "item.get",
          "params": {
             "output": "extend",
             "filter": {
                "description": "agent.ping"
             },
             "hostids": [
                "10051"
             ]
          },
          "id": 1,
          "auth": "7cd4e1f5ebb27236e820db4faebc1769"
       }

Обратите внимание, мы использовали параметр "filter", для указания описания элемента данных и "hostids", чтобы сказать что мы заинтересованы в элементе данных у узла сети, который мы создали (это было и его ID был 10051, помните?)

Ответ:

{
           "jsonrpc": "2.0",
           "result": [
               {
                   "hosts": [
                       {
                           "hostid": "10051"
                       }
                   ],
                   "itemid": "22162",
                   "type": "0",
                   "snmp_community": "",
                   "snmp_oid": "",
                   "snmp_port": "161",
                   "hostid": "10051",
                   "description": "agent.ping",
                   "key_": "agent.ping",
                   "delay": "30",
                   "history": "90",
                   "trends": "365",
                   "lastvalue": null,
                   "lastclock": null,
                   "prevvalue": null,
                   "status": "0",
                   "value_type": "3",
                   "trapper_hosts": "",
                   "units": "",
                   "multiplier": "0",
                   "delta": "0",
                   "prevorgvalue": null,
                   "snmpv3_securityname": "",
                   "snmpv3_securitylevel": "0",
                   "snmpv3_authpassphrase": "",
                   "snmpv3_privpassphrase": "",
                   "formula": "0",
                   "error": "",
                   "lastlogsize": "0",
                   "logtimefmt": "",
                   "templateid": "0",
                   "valuemapid": "0",
                   "delay_flex": "",
                   "params": "",
                   "ipmi_sensor": "",
                   "data_type": "0",
                   "authtype": "0",
                   "username": "",
                   "password": "",
                   "publickey": "",
                   "privatekey": "",
                   "mtime": "0"
               }
           ],
           "id": 1
       }

Ничего себе, много ж информации здесь. Теперь попробуем и обновить элемент данных, изменим "snmp_port" на 162 и "item type" на SNMPV1. Метод item.update будет верным инструментом для этого.

Запрос:

{
          "jsonrpc":"2.0",
          "method":"item.update",
          "params":{
             "itemid":"22162",
             "snmp_port":"162",
             "type":1
          },
          "id":1,
          "auth":"7cd4e1f5ebb27236e820db4faebc1769"
       }

Обратите внимание, мы указали три параметра: "itemid", таким образом Zabbix будет знать какой элемент данных обновлять (не забывайте это!) и два параметра, которые мы хотим изменить. Кстати, откуда я знаю, что "type":1 означает SNMPV1? Это все есть в общем разделе элемента данных.

Ответ:

{
           "jsonrpc": "2.0",
           "result": {
               "itemids": [
                   "22162"
               ]
           },
           "id": 1
       }

Обычно, Zabbix возвращает ID претерпевшего изменение элемента.