Модуль интеграции с системой мониторинга – нужна обратная связь

Всем привет!

В разработке находится модуль для интеграции iTop с системами мониторинга. Всем желающим предлагаю попробовать его деле и получить финальную версию в обмен на обратную связь.

Что умеет модуль:

  1. создавать инциденты при возникновении аварий, назначать команду и агента;
  2. привязывать аварийные конфигурационные единицы к инцидентам;
  3. выполнять инциденты при восстановлении и возвращать в работу при повторении аварии;
  4. добавлять сообщения в журнал инцидента.

Модуль представляет собой расширение REST API iTop. Логика работы модуля полностью настраиваемая, правила обработки событий определяются в конфигурационном файле. Для различных групп мониторинга можно настроить разные правила обработки событий.

Вот несколько простых вопросов, на которые нужно ответить для участия в тестировании:

Все замечания, вопросы и пожелания по работе модуля пишите в комментариях к этому посту. После завершения тестирования (думаю, 1-2 месяца) будет выпущена финальная версия.

Документация к модулю

Развернуть / свернуть

Общие сведения

Модуль добавляет в HTTP API iTop новый метод, с помощью которого можно выполнить несколько действий одним HTTP-запросом из системы мониторинга, например создать инцидент, привязать КЕ, назначить на нужного агента и написать сообщение в журнал.

Основные задачи модуля:

  • упростить настройку и поддержку систем мониторинга в части отправки событий в iTop;
  • свести к минимуму количество разнообразных скриптов для отправки запросов;
  • вернуть все специфичные данные из скриптов обратно в iTop (услуги, команды, агенты и т.п.).

Установка

Установка выполняется по стандартной процедуре. Модуль не изменяет модель данных iTop и после тестирования может быть удален из системы без негативных последствий.

Требования

PHP 7, iTop 2.6 и выше (на более ранних версиях iTop работа не проверялась), модули Simple Ticket Management или Incident Management.

Передача информации о событии мониторинга в iTop

Пример запроса (что нужно передать в параметре json_data):

{
  "operation": "monitoring/alarm",
  "comment": "Наш Zabbix",
  "context": "zabbix_servers",
  "ci_key": "Server2 (Grenoble)",
  "state": true,
  "message": "PROBLEM: host Server2 (Grenoble) unavailable",
  "output_fields": "ref,title,status,team_id_friendlyname,agent_id_friendlyname,functionalcis_list"
}

В зависимости от настроек модуля данный запрос может приводить к различным действиям в iTop.

Параметры запроса

operation

Значение monitoring/alarm – единственная доступная в настоящее время операция.

comment

Комментарий, который будет указан в истории создаваемого/изменяемого тикета.

context

Название контекста обработки события мониторинга, в котором задаются правила обработки (см. параметры модуля).

ci_key

Идентификатор, который будет использоваться для поиска соответствующей КЕ в iTop.

state

Состояние события мониторинга: true или 1 – авария началась, false или 0 – авария закончилась.

message

Текстовое сообщение события мониторинга.

output_fields

Атрибуты тикета, которые нужно вернуть в ответе на HTTP-запрос (см. описание стандартного API iTop).

Настройка модуля

При поступлении HTTP-запроса айтоп последовательно:

  1. с помощью ci_oql ищет КЕ, которая сгенерировала событие мониторинга;
  2. с помощью ticket_oql ищет тикет, относящийся к данному событию;
  3. выполняет определенные действия (создать, назначить, написать в журнал и т.д.).

Блок настроек модуля разбивается на контексты обработки событий. Внутри каждого контекста задаются собственные правила обработки события.

Пример конфигурации модуля с одним контекстом zabbix_servers:

'knowitop-monitoring-api' => array(
    'zabbix_servers' => array(
        'ci_oql' => 'SELECT Server WHERE name = :alarm->ci_key AND status = \'production\'',
        'ticket_oql' => 'SELECT UserRequest AS i JOIN lnkFunctionalCIToTicket AS lnk ON lnk.ticket_id = i.id JOIN Server AS ci ON lnk.functionalci_id = ci.id WHERE ci.name = :alarm->ci_key AND i.request_type = \'incident\' AND i.status NOT IN (\'closed\')',
        'actions_on_problem' => array(
            'create' => array(
                'fields' => array(
                    'org_id' => array('name' => '$ci->org_id->name$'),
                    'caller_id' => 'SELECT Person WHERE org_id = $ci->org_id$ AND id = 2',
                    'title' => 'Авария: $alarm->message$',
                    'description' => 'Авария: $alarm->message$ на КЕ $ci->name$',
                    'service_id' => 2,
                ),
            ),
            'assign' => array(
                'fields' => array(
                    'team_id' => 'SELECT Team AS t JOIN lnkContactToFunctionalCI AS lnk1 ON lnk1.contact_id = t.id JOIN Server AS ci ON lnk1.functionalci_id = ci.id WHERE ci.id = $ci->id$',
                    'agent_id' => 10,
                    'private_log' => 'Авария: $alarm->message$',
                ),
            ),
            'reopen',
            'write_to_log' => array(
                'log_att_code' => 'private_log',
                'text' => 'Появилась авария: $alarm->message$',
            ),
        ),
        'actions_on_ok' => array(
            'resolve' => array(
                'fields' => array(
                    'resolution_code' => 'other',
                    'solution' => 'Работа КЕ $ci->name$ восстановлена.',
                ),
            ),
            'write_to_log' => array(
                'log_att_code' => 'private_log',
                'text' => 'Завершилась авария: $alarm->message$',
            ),
        ),
    ),
),

Параметры контекста

ci_oql

OQL-запрос для поиска КЕ. Найденная КЕ будет автоматически связана с создаваемым тикетом. В запросе можно использовать следующие параметры: alarm->ci_key, alarm->state, alarm->message.

Пример: SELECT Server WHERE name = :alarm->ci_key AND status = 'production'.

ci_key_regexp

Регулярное выражение для преобразования переданного в HTTP-запросе параметра ci_key. Может быть полезно, если идентификатор КЕ в айтопе и в системе мониторинга совпадают частично. В регулярном выражении должна быть определена скобочная группа, совпадение с которой будет помещено в параметр alarm->ci_key.

Пример: /(Server\\d+)/. Если из системы мониторинга придет My super Server2 (Grenoble), в alarm->ci_key попадёт Server2.

ticket_oql

OQL-запрос для поиска тикета. Найденный тикет будет считаться относящимся к поступившему событию мониторинга. В запросе можно использовать следующие параметры: alarm->ci_key, alarm->state, alarm->message, ci->att_code (где att_code – атрибут найденной КЕ).

Пример: SELECT Incident AS i JOIN lnkFunctionalCIToTicket AS lnk ON lnk.ticket_id = i.id JOIN Server AS ci ON lnk.functionalci_id = ci.id WHERE ci.name = :alarm->ci_key AND i.status != 'closed'.

actions_on_problem

Список действий, которые будут выполнены над тикетом при поступлении события начала аварии ("state": 1). Доступные действия: create, assign, reopen, write_to_log. См. описание действий ниже.

actions_on_ok

Список действий, которые будут выполнены над тикетом при поступлении события окончания аварии ("state": 0). Доступные действия: resolve, write_to_log. См. описание действий ниже.

Действия над тикетом

Последовательность выполнения действий фиксированная, если какое-то из определенных действий неприменимо к тикету, оно пропускается. Например, для actions_on_problem заданы следующие действия create, assign, reopen, write_to_log. Если ticket_oql не вернул тикет, айтоп создаст новый тикет, затем назначит его и напишет сообщение в журнал. Действие reopen будет проигнорировано. Если ticket_oql вернул тикет в статусе Выполнен, айтоп вернет тикет в работу и напишет сообщение в журнал. Действия create и assign в данном случае будут проигнорированы.

create

Создать новый тикет, если запрос ticket_oql не нашел существующий тикет. В параметре fields должны быть переданы атрибуты создаваемого тикета. Внутри значений fields можно использовать заменители (плейсхолдеры): $alarm->ci_key$, $alarm->state$, $alarm->message$, $ci->att_code$ (где att_code – атрибут найденной КЕ).

Пример:

'create' => array(
    'fields' => array(
        'org_id' => array('name' => '$ci->org_id->name$'),
        'caller_id' => 'SELECT Person WHERE org_id = $ci->org_id$ AND id = 2',
        'title' => 'Авария: $alarm->message$',
        'description' => 'Авария: $alarm->message$ на КЕ $ci->name$',
        'service_id' => 2,
    ),
),

assign

Назначить созданный или найденный тикет. Параметры аналогичны действию create, к упомянутым выше заменителям добавляется $ticket->att_code$, где att_code – атрибут назначаемого тикета.

'assign' => array(
    'fields' => array(
        'team_id' => 'SELECT Team AS t JOIN lnkContactToService AS lnk ON lnk.contact_id = t.id JOIN Service AS s ON lnk.service_id = s.id WHERE s.id = $ticket->service_id$',
        'agent_id' => 10,
        'private_log' => 'Авария: $alarm->message$',
    ),
),

resolve

Выполнить назначенный тикет. Параметры аналогичны действию assign.

reopen

Вновь открыть выполненный тикет. Параметры аналогичны действию assign.

write_to_log

Добавить сообщение в журнал тикета. В параметрах указывается атрибут журнала (по умолчанию private_log) и тест сообщений (по умолчанию $alarm->message$). Все описанные выше заменители также доступны.

Пример:

'write_to_log' => array(
    'log_att_code' => 'private_log',
    'text' => 'Авария $alarm->message$ на КЕ $ci->name$',
),

Ограничения

  • Тикеты только Incident или UserRequest.
  • Каждое действие – отдельная операция обновления. Если в процессе выполнения последовательности действий происходит ошибка, откат к начальному состоянию не производится, и выполненные успешно действия не отменяются.

Примеры конфигов

Пример POST-запроса, который должна отправить система мониторинга при возникновении аварии:

POST http://localhost:8000/webservices/rest.php?version=1.4
Authorization: Basic cmVzdDpyZXN0
Content-Type: application/x-www-form-urlencoded

json_data={
  "operation": "monitoring/alarm",
  "comment": "Monitoring System",
  "context": "demo_context",
  "ci_key": "Server4",
  "state": 1,
  "message": "Server4 is down",
  "output_fields": "title,status,team_id_friendlyname,agent_id_friendlyname,solution"
}

Тот же запрос через cURL:

curl -X POST --location "http://localhost:8000/webservices/rest.php?version=1.4" \
    -H "Authorization: Basic cmVzdDpyZXN0" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "json_data={
  \"operation\": \"monitoring/alarm\",
  \"comment\": \"Monitoring System\",
  \"context\": \"demo_context\",
  \"ci_key\": \"Server4\",
  \"state\": 1,
  \"message\": \"Server4 is down\",
  \"output_fields\": \"title,status,team_id_friendlyname,agent_id_friendlyname,solution\"
}"

// TODO: add config examples

2 лайка

Добрый день, хочу попробовать

Отлично! Ответил в личном сообщении.

Хочу опробовать модуль!

@Bboss, написал в личку!

Добрый день хотел бы опробовать модуль

Привет, все!
Выслал ссылку на загрузку модуля тем, кто отправлял заявку на тестирование. Если упустил кого-то, дайте знать.

Ну что? Кто-нибудь что-нибудь попробовал? Для каких сценариев расписать пример конфига?

Добрый день! Если актуально хотел бы участвовать!

Отправил в личном сообщении. Пожелания и замечания пиши сюда.

Да всё получил! Спасибо!

Прошу помочь с настройкой между iTop и Zabbix.

как я понял Zabbix должен присылать HTTP / POST запросы iTop как описано здесь: https://www.itophub.io/wiki/page?id=2_6_0%3Aadvancedtopics%3Arest_json
С такими значениями:
«В зависимости от настроек модуля данный запрос может приводить к различным действиям в iTop.
Параметры запроса
operation
Значение monitoring/alarm – единственная доступная в настоящее время операция.

comment
Комментарий, который будет указан в истории создаваемого/изменяемого тикета.

context
Название контекста обработки события мониторинга, в котором задаются правила обработки (см. параметры модуля).

ci_key
Идентификатор, который будет использоваться для поиска соответствующей КЕ в iTop.

state
Состояние события мониторинга: true или 1 – авария началась, false или 0 – авария закончилась.

message
Текстовое сообщение события мониторинга.
output_fields
Атрибуты тикета, которые нужно вернуть в ответе на HTTP-запрос (см. описание стандартного API iTop 1).»
Если я правильно понял, тогда в Zabbix нужно добавить расширение типа такого: https://www.zabbix.com/ru/integrations/itop
чтобы Zabbix понимал что ему и куда отправлять? Верно? Поправьте меня если я ошибаюсь

Нет. Это отдельное расширение, которое само умеет что-то отправлять в айтоп (только хз, что именно и как). Для работы нашего модуля интеграции это расширение ставить не нужно, они не будут дружить.

Чтобы заббикс понимал, что и куда отправить, нужно в нём это как-то настроить)) В общем случае задача простая и сводится к отправке HTTP запроса при возникновении события. Какими инструментами это можно сделать, спросите своего администратора заббикса. Я делал это простым пользовательским скриптом с curl внутри. По смыслу это и есть webhook. Если есть возможность добавить свой вебхук в заббикс, это было бы удобнее, чем скрипт.

Модуль интеграции не зависит от конкретной системы мониторинга, не требует хранения какой-либо информации о созданном тикете на стороне системы мониторинга для обновления тикета (хотя это можно сделать для удобства пользователей) и использует один формат запроса для всех событий. Системе мониторинга не нужно думать, есть ли тикет, открыт он или закрыт и т.п. Её задача просто отправить стандартный запрос с состоянием события, а логика обработки этого события настраивается в iTop.

Спасибо за ответ! Ещё спрошу может не тут нужно, но всё же) Как можно выгрузить (через например через API) из Zabbix в iTop заведённые КЕ? На данный момент есть рабочий Zabbix и пустой iTop, хочется их синхронизировать чтобы пользоваться в полной мере iTop. Возможно посоветуете что-то. Я настроил синхронизацию iTop и OCS Inventory через Data collector for OCS Inventory, но Zabbix более настроен и хотелось бы использовать синхронизацию именно с Zabbix. Надеюсь мой вопрос понятен)

Короткий ответ:
Не знаю, с заббиксом я на уровне пользователя. Под его API можно сделать аналогичный Data Collector, нужно только знать этот API.

Длинный ответ:

А надо ли iTop синхронизировать с Zabbix? В моём представлении система мониторинга/инвентаризации и база конфигурационных единиц (CMDB) имеют различное назначение, и информация в них относительно одних и тех же объектов также будет различная. Не все хосты в заббиксе будут КЕ в CMDB, как и не каждая KE должна быть хостом заббикса. Не думаю, что оперативную информацию о техническом состоянии объекта нужно хранить в CMDB.

Я бы рассматривал CMDB как источник сведений об эталонном состоянии КЕ (которое обеспечивает требуемый уровень оказания услуг, построенных на этих КЕ), а систему мониторинга как источник сведений о текущем состоянии. В этом случае появляются возможности для отслеживания несанкционированных изменений и внедрения процесса управления изменениями, в рамках которого согласовываются изменения эталонного состояния, а затем к нему приводятся и фактические характеристики объектов.

Конечно, CMDB и система мониторинга должны быть связаны каким-то образом, чтобы обеспечить просмотр информации и быстрый переход между системами (как минимум). Один из способов вот такой. То есть данные из системы мониторинга подгружаются онлайн, а не хранятся в CMDB. Для такой связи в CDMB нужно хранить только ID объекта в системе мониторинга.

Добрый день!

Владимир спасибо за ответ! Для тестирования хочется пока проверить работу тестовыми скриптами на сервере iTop, пробую имитировать сообщение пользовательским скриптом с curl и у меня возникает ошибка:

root@itop:/home/kasatkin# ./test_2
./test_2: line 2: curl: command not found

Сам curl:

curl -X POST --location “http://localhost:8000/webservices/rest.php?version=1.4
-H “Authorization: test test”
-H “Content-Type: application/x-www-form-urlencoded”
-d “json_data={
"operation": "monitoring/alarm",
"comment": "Monitoring System",
"context": "demo_context",
"ci_key": "113",
"state": 1,
"message": "Server4 is down",
"output_fields": "title,status,team_id_friendlyname,agent_id_friendlyname,solution"
}”

я убрал логин и пароль
тоже самое через POST-запрос:

root@itop:/home/kasatkin# ./test_2
Please enter content (application/x-www-form-urlencoded) to be POSTed:
^C

Сам POST-запрос:

POST http://localhost:8000/webservices/rest.php?version=1.4
Authorization: test test
Content-Type: application/x-www-form-urlencoded

json_data={
“operation”: “monitoring/alarm”,
“comment”: “Monitoring System”,
“context”: “demo_context”,
“ci_key”: “113”,
“state”: 1,
“message”: “Server4 is down”,
“output_fields”: “title,status,team_id_friendlyname,agent_id_friendlyname,solution”
}

Авторизация идёт через пользователя REST_API, пароль я изменил в сообщении, но пользователь рабочий.
Вопрос что нужно для 2-й строчки и опишите где брать ci_key? ci_key это наименование или id(Первичный ключ)? Или это нужно дополнительно настраивать в конфигурации модуля? Заранее спасибо!

Эмм… где вопрос, там и ответ. Сам curl не забыл на сервер поставить?)

Кавычки нужно экранировать. Смотри мой пример в первом посте.

Заголовок HTTP Basic Auth (Basic access authentication - Wikipedia).

А теперь к теме поста.

Его не надо брать, его надо задавать. ci_key используется в ci_oql после преобразования с помощью ci_key_regexp:

В этом и прикол модуля – система мониторинга и айтоп не требуют строгого соответствия по id между хостами и КЕ. При настройке модуля нужно самому решить, через какие атрибуты системы будут сопоставлять хост и КЕ. В ci_key система мониторинга передаёт то, с помощью чего в дальнейшем айтоп будет искать КЕ. Это может быть IP-адрес, имя или id хоста или ещё что-то. То, что передано в ci_key будет доступно в ci_oql в виде плейсхолдера alarm->ci_key.

Если мы передаём из системы мониторинга в ci_key IP-адрес, то в айтопе ci_oql может иметь вид: SELECT NetworkDevice WHERE ip_address = :alarm->ci_key.

Еще пример. Предположим, в организации (о чудо!) у каждого сервера есть уникальный десятизначный номер (номер актива). В айтопе он указан в поле asset_number. А с системой мониторинга админы заленились и просто пишут его в названии хоста (ну хоть так!). Вот так в айтопе – 1002000121, вот так в системе мониторинга – msk-vpn-server 1002000121 (CSR). В этом случае система мониторинга может передавать в ci_key всё название хоста целиком, в айтопе ci_oql будет SELECT PhysicalDevice WHERE asset_number = :alarm->ci_key, но еще будет задан ci_key_regexp с регуляркой /\\b(\\d{10})\\b/, которая выберет из названия хоста только нужный кусок с номером актива. Теперь плейсхолдер :alarm->ci_key в ci_oql будет содержать только 10 цифр номера актива.

Владимир, добрый день.

Оставил заявку через docs.google. Если ещё актуально.

Добрый день, ссылка на модуль в личном сообщении.