Доброго времени суток, в общем, в компании, в которой я работаю, используется 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 в шаблоне создается элемент данных, который как раз и будет опрашивать предполагаемый узел:
После создания основного элемента данных создается правило обнаружения, где как раз и происходит парсинг JSON ответа.
Все полученные данные из JSON записываются в LLD Макросы.
Наименование макросов лаконичное, поэтому, думаю, не должно возникнуть проблем с пониманием, какой макрос за что отвечает.
Теперь у нас есть IP-адрес, имя и статус камеры, можно переходить в прототипы элементов данных этого правила обнаружения
Создано 2 прототипа элемента данных,
CAMERA [{#NAME}]: Get record status
-
Получение состояние записи камеры, ведет ли она архивную запись
Ivideon Get Data: CAMERA [{#NAME}]: Get Status
-
Получение статуса камеры
Это зависимый элемент данных, он ссылается на созданный ранее основной элемент данных, где происходит получение JSON ответа.
Теперь разберем, как шаблон получает состояние записи архива камеры с помощью прототипа элемента данных 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/