SNMP MIB браузер на Perl и JavaScript

от автора

Что делать на работе, если не знаешь, чем бы еще заняться? Конечно же писать на Хабр!

Благодаря нашим доблестным законодателям, дальнейшее развитие бизнеса самостоятельно нерентабельно и мы уходим под более крупного оператора. Вот у меня и сложилась такая ситуация, что смысла дорабатывать, переписывать и исправлять свои старые проекты — нет, у «крупняка» все сервисы свои. Сижу, курю. А потом думаю, а чего сидеть-то, напишу-ка я на Хабр. Статья прошла модерацию, «И тут Остапа понесло…».

Итак, о чем будет эта статья. Все кто занимаются сетями, рано или поздно сталкиваются с MIB. Для тех, кому лень переходить по ссылке, это такая база данных, содержащая информацию об объекте, в нашем случае — сетевом устройстве. На хабре было несколько статей, посвященным работе с MIB и возникающим при этом вопросах. Мне понравилась статья SNMP MIBs и как их готовить, где автор для работы с MIB использовал инструмент от D-Link — утилиту D-View. Сразу скажу, зная качество MIB от этого вендора — использовать в реальных проектах D-View не рекомендую. Однако она дает представление, о типичном интерфейсе подобного программного обеспечения. Как ни странно, программ для работы непосредственно с MIB, сходных по функционалу хотя бы с D-View — не так много. Я бы даже сказал — очень мало. Описывать все их плюсы и минусы я не собираюсь. Здесь я хочу показать мою реализацию, наверняка не самую лучшую, но писалось «для себя» и функционал допиливался по мере необходимости.

Итак, вся серверная часть будет на Perl и библиотеке SNMP.pm. Пожалуй разобью статью на две части, — во второй будет описание клиентской части. Начнем пожалуй с загрузки нужных нам MIB:

sub load_mibs {     my ($attr, $Nms) = @_;     #Если MIB Вашего оборудования располагаются в каталоге, отличном от     #стандартного(с моей точки зрения - это правильный подход), указываем здесь      my $MIB_search_path = '../modules/Nms/mibs';          #Добавляем свой путь во внутренний лист библиотеки     SNMP::addMibDirs($MIB_search_path);     SNMP::addMibDirs($MIB_search_path . '/private');          #Здесь уже можно загрузить все модули, но при работе с реальным уст-ом     #я загружаю только нужные мне.     if ( $attr->{ALL} ) {         SNMP::addMibFiles( glob( $MIB_search_path . '/private' . '/*' ) );         SNMP::initMib();     }     #Пусть это будет DES3200-28     elsif ( $attr->{SYS_ID} ) {         my @mods = ('EQUIPMENT-MIB', 'DES3200-28-L3MGMT-MIB', 'CABLE-DIAG-MIB');         #Здесь, в отличии от первого варианта, загрузятся только нужные MIB         SNMP::loadModules(@mods);         SNMP::initMib();     }          return 1; }

Сразу несколько пояснений: — первое, загрузка только нужных модулей, значительно ускоряет дальнейшую работу с деревом OID; — второе, не обязательно указывать все необходимые модули, в правильно «приготовленном» MIB используются ссылки на нужные модули, и они подгрузятся автоматически, например так:

IMPORTS     MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,     OBJECT-IDENTITY, Counter32, Gauge32, Integer32, mib-2         FROM SNMPv2-SMI     DisplayString, TimeStamp, TimeInterval, TestAndIncr,       AutonomousType, TEXTUAL-CONVENTION         FROM SNMPv2-TC     MODULE-COMPLIANCE, OBJECT-GROUP         FROM SNMPv2-CONF;

то есть указывается, что и откуда импортировать.

Поехали дальше, дерево с OID у нас уже есть и находится в хеше %SNMP::MIB. В принципе, можно его уже в таком виде отдать клиенту, и распарсить какой-нибудь JS библиотекой. Но мы добрые, — не дадим зависнуть клиентской машинке и приготовим данные сервером. Для отрисовки дерева я буду использовать библиотеку jsTree, следующий код подготавливает данные:

sub mibs_tree {      my ($attr) = @_;      my %labels;     my @tree_arr;          foreach my $oid ( sort keys(%SNMP::MIB) ) {     		#Определяем ветку дерева, либо корень.         my $prev_id =               ( $SNMP::MIB{$oid}{parent} )               ? $SNMP::MIB{$oid}{parent}{objectID}               : '#';                  #Ну и дальше мы определяем типы OID и навешиваем атрибуты для jsTree         my $icon = '';                 my %type;         if ( $SNMP::MIB{$oid}{children}[0]{indexes}[0] ) {         	$type{type} = 'table';         }         elsif ($SNMP::MIB{$oid}{parent} && $SNMP::MIB{$oid}{parent}{indexes}[0]){         		$type{type} = 'row';         }         elsif ( $SNMP::MIB{$oid}{type} ) {         		$type{type} = 'scalar';         }         elsif ( $SNMP::MIB{$oid}{indexes}[0] ) {         		$type{type} = 'indexes';         }         else {         		$type{type} = 'folder';         }         push @tree_arr,               (                 {                     id     => $SNMP::MIB{$oid}{objectID},                     text   => $SNMP::MIB{$oid}{label},                     parent => $prev_id,                     %type                 }               );         }     }      my %types = (         table   => { icon => 'fa fa-table' },         row     => { icon => 'fa fa-columns' },         scalar  => { icon => 'fa fa-paragraph' },         indexes => { icon => 'fa fa-list-ul' },         folder  => { icon => 'fa fa-folder-o' },     );          return make_tree(         {             plugins => [ 'types', 'search', 'contextmenu' ],             contextmenu => { items => '*customMenu*' },             types       => \%types,             core        => { data  => \@tree_arr }         }     ); }

На этом пожалуй пока остановлюсь, так как дальше будет уже много JS и HTML. Для затравки покажу, что должно получится в результате:

Пишу, пока есть настроение и не факт, что продолжение будет. Поэтому дам ссылку на мою старенькую репку на github. Код рабочий, правда без комментариев, думаю имеющим опыт работы с Perl, не составит труда выдернуть нужные куски.

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


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *