Мониторинг сервиса Ivideon-server с помощью Zabbix

от автора

Доброго времени суток, в общем, в компании, в которой я работаю, используется Ivideon-server версии 3.9.0 либо 3.12.0. И появилась огромная потребность в мониторинге камер: их доступности, а также, пишется ли архив с этих камер. Поэтому я начал разработку шаблона Zabbix, который бы опрашивал сервера с Ivideon-server по API. Начал я с того, что с помощью WireShark я разобрал работу Ivideon Client.

Готовые шаблоны закреплю в конце статьи. А в статье постараюсь разобрать как они работают.
Первый запрос, что я смог вытащить и считаю его основным: http://IP-Адрес сервера/streams/info?server=1&sessionId=пароль от сервера, при отправке которого мы получаем JSON ответ:

[{    "achannels" : 0,    "acodec" : "none",    "afreq" : 0,    "archive" : {        "edge" : false,        "internal_speed_play" : false,        "key_frame_seek" : true,        "smooth_speed_play" : 4,        "speeds" : [ 1, 2, 4, 8, 16, 32, 64 ],        "writable" : true    },    "custom_device_info" : {        "fw_version" : "2.800.0000000.12.R 2021-04-30",        "hardware_id" : "1.00",        "ipv4" : "19.44.0.27",        "model" : "DH-IPC-HDW1230T1P-0280B",        "name" : "401 ближний кабинет",        "serial_number" : "",        "serial_number_format" : "onvif",        "vendor" : "Dahua"    },    "features" : {        "analytics_info" : { }    },    "height" : 960,    "id" : 1245184,    "instance_id" : "",    "is_forced_as_active" : false,    "is_turned_off" : false,    "name" : "401 ближний кабинет",    "online" : true,    "preview" : {        "0" : false,        "1" : false,        "2" : false    },    "record" : {        "scheduled" : true,        "type" : "continuous"    },    "sources" : {        "0" : null,        "1" : "rtsp://admin:viewer121@0.0.0.0/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif",        "2" : "rtsp://admin:viewer121@0.0.0.0/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif"    },    "status" : 1,    "streams" : {        "0" : false,        "1" : true,        "2" : true    },    "vcodec" : "h265",    "width" : 1280}]

Здесь уже есть большая часть необходимых нам данных, IP‑Адреса камер в элементе «ipv4» а также их статус «status» где 0 — не работает 1 — работает.

Далее в Zabbix в шаблоне создается элемент данных, который как раз и будет опрашивать предполагаемый узел:

Основной элемент данных в шаблоне Zabbix

Основной элемент данных в шаблоне Zabbix

После создания основного элемента данных создается правило обнаружения, где как раз и происходит парсинг JSON ответа.

Правило обнаружения

Правило обнаружения
Предобработка JSONPath

Предобработка JSONPath

Все полученные данные из JSON записываются в LLD Макросы.

LLD Макросы

LLD Макросы

Наименование макросов лаконичное, поэтому, думаю, не должно возникнуть проблем с пониманием, какой макрос за что отвечает.

Теперь у нас есть IP-адрес, имя и статус камеры, можно переходить в прототипы элементов данных этого правила обнаружения

Прототипы элементов данных

Прототипы элементов данных

Создано 2 прототипа элемента данных,

CAMERA [{#NAME}]: Get record status

  • Получение состояние записи камеры, ведет ли она архивную запись

Ivideon Get DataCAMERA [{#NAME}]: Get Status

  • Получение статуса камеры

Ivideon Get Data: CAMERA [{#NAME}]: Get Status

Ivideon Get Data: CAMERA [{#NAME}]: Get Status

Это зависимый элемент данных, он ссылается на созданный ранее основной элемент данных, где происходит получение JSON ответа.

Предобработка элемента данных

Предобработка элемента данных

Теперь разберем, как шаблон получает состояние записи архива камеры с помощью прототипа элемента данных CAMERA [{#NAME}]: Get record status

CAMERA [{#NAME}]: Get record status

CAMERA [{#NAME}]: Get record status

Этот элемент данных имеет тип скрипт, мною сделан небольшой Java скрипт который отправляет запрос на сервер по камере.

var obj = JSON.parse(value);var host_ip = obj.hostip;var camera_id = obj.cameraid;var ivideon_pass = obj.ivideon_passwordvar request = new HttpRequest();var nowUnix = Math.floor(Date.now() / 1000);var timestamp_offset = nowUnix - 10800var url = "http://" + host_ip + ":8080/archive/list"        + "?startTime=" + timestamp_offset        + "&endTime=" + nowUnix        + "&server=1&sessionId=" + ivideon_pass        + "&camera=" + camera_id;var data = JSON.parse(request.get(url));if (Array.isArray(data) && data.length === 0) {    return 0;} else {    return 1;}

В параметрах прототипа данных указывается все те макросы, что мы вытащили ранее.

Теперь когда у нас есть данные можно делать прототипы триггеров.

Прототипы триггеров

Прототипы триггеров

Camera {#NAME} archive not recording — ведется ли архив

Camera {#NAME} is unavailable — статус камеры

Ведется ли архив

Ведется ли архив

Скрипт созданный ранее имеет 2 варианта ответа, 0 — архив не ведется 1 — архив пишется, соответственно, в прототипе триггера для его срабатывания он должен получить 0, тогда триггер сработает.

Статус камеры

Статус камеры

В прототипе Camera {#NAME} is unavailable применяется тот же принцип 0 — не работает 1 — работает.

На этом шаблон готов. Далее создаем узел сети с применением этого шаблона.

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

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

Тип интерфейса SNMP. Также необходимо указать в макросах узла сети следующий макрос: {$IVIDEON_PASSWORD}, в значение записать пароль используемый для подключение к Ivideon-server.

Макрос узла сети

Макрос узла сети

После создания узла сети в элементах данных можно увидеть созданные правилом обнаружения элементы, по каждой камере создается отдельный элемент данных.

Элементы данных узла сети

Элементы данных узла сети

Сразу после появления элементов данных правило обнаружения создает триггеры по каждому элементу данных.

Триггеры

Триггеры

На этом всё, все работы и тестирование проводились с версиями: Zabbix 7.4, ivideon‑server 3.9 и ivideon‑server 3.12.0.

Готовый шаблон для версии Ivideon — server 3.9.0.

zabbix_export:  version: '7.4'  template_groups:    - uuid: d37f71c7e3f7469bab645852a69a2018      name: 'Templates/Video surveillance'  templates:    - uuid: d8d1bbd1d20346f7bb5153d23f024150      template: 'ivideon-server 3.9 HTTP'      name: 'ivideon-server 3.9 HTTP'      groups:        - name: 'Templates/Video surveillance'      items:        - uuid: a8047c121f154cf2a37ff3a50d2cf52c          name: 'Ivideon Get Data'          type: HTTP_AGENT          key: ivideon.attributes          delay: 3m          value_type: TEXT          url: 'http:/{HOST.IP}:8080/streams/info'          query_fields:            - name: server              value: '1'            - name: sessionId              value: '{$IVIDEON_PASSWORD}'          output_format: JSON          triggers:            - uuid: 6aebb2b119844e7c8223e90a9afbeba9              expression: 'nodata(/ivideon-server 3.9 HTTP/ivideon.attributes,3m)=1'              name: 'Ivideon-server service is unavailable'              priority: HIGH      discovery_rules:        - uuid: 9a759a9eb47049a2bbf8e9effea1456b          name: 'Ivideon-server discovery cameras'          type: DEPENDENT          key: ivideon.cameras          item_prototypes:            - uuid: 9a900ef7424f4d00bd3200f7ecb161e3              name: 'CAMERA [{#NAME}]: Get record status'              type: SCRIPT              key: 'ivideon.cameras.record.status[{#NAME}]'              value_type: TEXT              params: |                var obj = JSON.parse(value);                                var host_ip = obj.hostip;                var camera_id = obj.cameraid;                var ivideon_pass = obj.ivideon_password                var request = new HttpRequest();                                var nowUnix = Math.floor(Date.now() / 1000);                var timestamp_offset = nowUnix - 10800                                var url = "http://" + host_ip + ":8080/archive/list"                        + "?startTime=" + timestamp_offset                        + "&endTime=" + nowUnix                        + "&server=1&sessionId=" + ivideon_pass                        + "&camera=" + camera_id;                                var data = JSON.parse(request.get(url));                                if (Array.isArray(data) && data.length === 0) {                    return 0;                } else {                    return 1;                }              parameters:                - name: cameraid                  value: '{#CAMERA_ID}'                - name: hostip                  value: '{HOST.IP}'                - name: ivideon_password                  value: '{$IVIDEON_PASSWORD}'              trigger_prototypes:                - uuid: 2c4c9a05f32d43f38e6d0a58c6e1d63e                  expression: 'last(/ivideon-server 3.9 HTTP/ivideon.cameras.record.status[{#NAME}])=0'                  name: 'Camera {#NAME} archive not recording'                  priority: WARNING                  dependencies:                    - name: 'Camera {#NAME} is unavailable'                      expression: 'last(/ivideon-server 3.9 HTTP/ivideon.cameras.status[{#NAME}])=0'                    - name: 'Ivideon-server service is unavailable'                      expression: 'nodata(/ivideon-server 3.9 HTTP/ivideon.attributes,3m)=1'            - uuid: f76677285bf74103acdc473a92aad686              name: 'CAMERA [{#NAME}]: Get Status'              type: DEPENDENT              key: 'ivideon.cameras.status[{#NAME}]'              trends: '0'              preprocessing:                - type: JSONPATH                  parameters:                    - '$.body[?(@.name=="{#NAME}")].status.first()'              master_item:                key: ivideon.attributes              trigger_prototypes:                - uuid: 4f0bd15b54b2442cba8805f361787d7f                  expression: 'last(/ivideon-server 3.9 HTTP/ivideon.cameras.status[{#NAME}])=0'                  name: 'Camera {#NAME} is unavailable'                  priority: HIGH                  dependencies:                    - name: 'Ivideon-server service is unavailable'                      expression: 'nodata(/ivideon-server 3.9 HTTP/ivideon.attributes,3m)=1'          master_item:            key: ivideon.attributes          lld_macro_paths:            - lld_macro: '{#CAMERA_ID}'              path: $.id            - lld_macro: '{#NAME}'              path: $.name            - lld_macro: '{#STATUS}'              path: $.status          preprocessing:            - type: JSONPATH              parameters:                - '$.body[*]'

Готовый шаблон для версии Ivideon-Server 3.12.0

zabbix_export:  version: '7.4'  template_groups:    - uuid: d37f71c7e3f7469bab645852a69a2018      name: 'Templates/Video surveillance'  templates:    - uuid: 8799d6b58bf3483895babbd76026c758      template: 'ivideon-server 3.12 HTTP'      name: 'ivideon-server 3.12 HTTP'      groups:        - name: 'Templates/Video surveillance'      items:        - uuid: a724aaa44e6e4c0d8c5fbadcb3247fa6          name: 'Ivideon Get Data'          type: HTTP_AGENT          key: ivideon.attributes          delay: 3m          value_type: TEXT          url: 'http:/{HOST.IP}:8080/streams/info'          query_fields:            - name: server              value: '1'            - name: sessionId              value: '{$IVIDEON_PASSWORD}'          output_format: JSON          triggers:            - uuid: 13e35f3290e644f09bead7f9caf78ab1              expression: 'nodata(/ivideon-server 3.12 HTTP/ivideon.attributes,3m)=1'              name: 'Ivideon-server service is unavailable'              priority: HIGH      discovery_rules:        - uuid: 66bdeec591ac4239806f6c86c0179afd          name: 'Ivideon-server discovery cameras'          type: DEPENDENT          key: ivideon.cameras          item_prototypes:            - uuid: 685ba95a1f364e1b958106b4d1eb76a0              name: 'CAMERA [{#NAME}]: Get record status'              type: SCRIPT              key: 'ivideon.cameras.record.status[{#NAME}]'              value_type: TEXT              params: |                var obj = JSON.parse(value);                                var host_ip = obj.hostip;                var camera_id = obj.cameraid;                var ivideon_pass = obj.ivideon_password                var request = new HttpRequest();                                var nowUnix = Math.floor(Date.now() / 1000);                var timestamp_offset = nowUnix - 10800                                var url = "http://" + host_ip + ":8080/archive/list"                        + "?startTime=" + timestamp_offset                        + "&endTime=" + nowUnix                        + "&server=1&sessionId=" + ivideon_pass                        + "&camera=" + camera_id;                                var data = JSON.parse(request.get(url));                                if (Array.isArray(data) && data.length === 0) {                    return 0;                } else {                    return 1;                }              parameters:                - name: cameraid                  value: '{#CAMERA_ID}'                - name: hostip                  value: '{HOST.IP}'                - name: ivideon_password                  value: '{$IVIDEON_PASSWORD}'              trigger_prototypes:                - uuid: 787126b8f33d4a75b8a038013a4e273e                  expression: 'last(/ivideon-server 3.12 HTTP/ivideon.cameras.record.status[{#NAME}])=0'                  name: 'Camera {#NAME} archive not recording'                  priority: WARNING                  dependencies:                    - name: 'Camera {#NAME} is unavailable'                      expression: 'last(/ivideon-server 3.12 HTTP/ivideon.cameras.status[{#NAME}])=0'                    - name: 'Ivideon-server service is unavailable'                      expression: 'nodata(/ivideon-server 3.12 HTTP/ivideon.attributes,3m)=1'            - uuid: 4e5d1fd4cb4c4f73b6cae860743c3cf3              name: 'CAMERA [{#NAME}]: Get Status'              type: DEPENDENT              key: 'ivideon.cameras.status[{#NAME}]'              trends: '0'              preprocessing:                - type: JSONPATH                  parameters:                    - '$.body[?(@.custom_device_info.name=="{#NAME}")].status.first()'              master_item:                key: ivideon.attributes              trigger_prototypes:                - uuid: cf2488d8a103465b983c039ae415415c                  expression: 'last(/ivideon-server 3.12 HTTP/ivideon.cameras.status[{#NAME}])=0'                  name: 'Camera {#NAME} is unavailable'                  priority: HIGH                  dependencies:                    - name: 'Ivideon-server service is unavailable'                      expression: 'nodata(/ivideon-server 3.12 HTTP/ivideon.attributes,3m)=1'          master_item:            key: ivideon.attributes          lld_macro_paths:            - lld_macro: '{#CAMERA_ID}'              path: $.id            - lld_macro: '{#NAME}'              path: $.custom_device_info.name            - lld_macro: '{#STATUS}'              path: $.custom_device_info.status          preprocessing:            - type: JSONPATH              parameters:                - '$.body[*]'

Чтобы использовать шаблон, вставьте содержимое в текстовый файл и сохраните с расширением yaml, после импортируйте в Zabbix.

ссылка на оригинал статьи https://habr.com/ru/articles/1048898/