понедельник, 29 декабря 2014 г.

Опрос сетевых устройств по SNMP в Erlang

Где-то чуть более года назад понадобилось написать многопоточное приложение для опроса сетевых устройств. И так совпало, что необходимость написания такого приложения совпала с интересом к Erlang. Оказалось что задача эта как раз для Erlang. А тут еще и готовая библиотека есть в OTP для работы с SNMP. И документация к этой библиотеке есть.
Вот только документация мне показалась достаточно многословной и объемлющей, для моей весьма скромной задачи. Поэтому я и написал этот краткий экскурс. Надеюсь он кому-нибудь да пригодится.



Итак, терминология:

agent - сетевое устройство, которой можно опросить по SNMP;
manager - часть Erlang приложения snmp, отвечающая за базовые коммуникации с агентами и передачу SNMP сообщение от агента, соответствующему user. Тут имеет место pub/sub, где publisher - agent, subscriber - user.
user - модуль/процесс нашего приложения, отвечающий за обработку SNMP пакетов от зарегистрированных за ним агентов и реализующий поведение(behavioursnmpm_user; За одним пользователем может быть зарегистрировано произвольное количество агентов. Агент может быть зарегистрирован только за одним пользователем. Взаимоотношения между агентом, менеджером и юзером, являются ключевым моментом.

snmp - Erlang приложение, требующее небольшой конфигурации перед запуском.
Сконфигурировать snmp можно с помощью интерактивного конфигуратора , выполнив в REPL snmpm:config/0, либо руками добавив в наш sys.config тапл:

{snmp, [{manager, Options}]}
, Options описаны в документации.

В моем приложении вот такой простенький конфиг:

{priority, normal},
{versions, [v1,v2]},
{config, [{dir, "priv/manager/"}, {verbosity, silence}, {
db_dir, "priv/manager/"}, {repair, true}, {auto_save, 5000}]},
{inform_request_behaviour, auto},
{server, [{timeout,10000},{verbosity,silence}]},
{note_store, [{timeout,60000},{verbosity,silence}]},
{net_if, [{module,snmpm_net_if},{verbosity,silence},{options,[{bind_to,false},{no_reuse,false}]}]},
{def_user_mod, snms_snmp_callback}
 , а в каталоге priv/manager лежит файлик manager.conf вот такого содержания:

{port, 162}.
{engine_id, "mgrEngine"}.
{max_message_size, 1024}.
Это конфигурация самого менеджера. Опять же, все опции описаны в документации.

В конфигурации snmp, есть тапл {def_user_mod, snms_snmp_callback}.
Это опция указывающая на модуль реализующий default_user.
default_user это пользователь, обрабатывающий пакеты от агентов, которые не зарегистрированы ни за одним из пользователей.
В качестве этого пользователя может быть использован как модуль, идущий с приложением snmp - snmpm_default_user , так и модуль вашего приложения.
Модуль должен реализовать поведение snmpm_user.
Это поведение предполагает наличие следующих функций-обработчиков:
handle_error/3
handle_agent/4
handle_pdu/4
handle_trap/3
handle_inform/3
handle_report/3
handle_invalid_result/2
Подробное описание сигнатур этих функций можно найти в документации.

Модуль snmpm_default_user, идущий с snmp ничего особо полезного не делает, только лишь отправляет содержимое SNMP сообщений в error_logger и может быть полезен только на первых порах, для того чтобы глазками посмотреть на пакеты. В документации к OTP настоятельно рекомендуют его не использовать.

Итак, конфигурация есть. Запускаем snmp:
application:start(snmp).
Ну и это почти все. Дальше все достаточно банально.  Чтобы работать с агентом нам потребуется:
  1. зарегистрировать своего пользователя - snmpm:register_user/3 или snmpm:register_user/4;
  2. зарегистрировать за этим пользователем агента - snmpm:register_agent/3;
  3. выполняем set/get ф-ции (см. erl -man snmpm).
Все set/get функции имеются в двух ипостасях - синхронной и асинхронной. Соответственно при выполнении синхронной ф-ции текущий процесс блокируется до получения ответа, либо до истечения таймаута. Результат же выполнения асинхронной ф-ции мы получаем в нашем snmpm_user модуле (в моем примере это snms_snmp_callback) , в ф-ции handle_pdu.

Вот собственно и все. Дальше читайте документацию. Она, как я выше писал, довольно обширна.

Комментариев нет:

Отправить комментарий