SNMP MIB Browser (continued)

First, I want to go back a little. In the first part, I did not write why the MIB browser and the MIB modules themselves are generally needed, because many somehow manage without all this and quite monitor their networks for themselves. As a rule, a digital OID of the form " .1.3.6.1.4.1.171.11.113.1.3.2.2.3" is used for this and thematic forums are full of requests " Tell me the OID in order to ...". If you wish, you can find the required OID yourself by making a walk somewhere closer to the private branch .





The MIB browser is exactly the tool that will allow you to simplify your work with the equipment. This is actually the same as having a hierarchical structure in a database with fast and convenient searches, indexes, data types. You get quick access to all sensors and equipment triggers, with the ability to create / edit them. This makes it easier to administer networks, identify errors, and respond faster to faults. This is especially important when working with new models previously unknown to you.





Of course, a lot here depends on vendors, or rather on the quality of the MIBs they provide and the implementation of snmp on hardware. Modules often lack descriptions of the necessary indexes, the indexes do not correspond to the actual values ​​returned, etc. In general, there are situations beyond the bounds of logic - I have gepon equipment from one Chinese manufacturer, which has two different vendors in the enterprises branch ! So try to find the required OIDs by brute force. And it is not necessary to write "you are all cattle, buy only tsiski". I am exaggerating, of course, but often the comments sound like this. And I somehow judge a tsiska about osr . If the topic on working with MIB modules is interesting, I may return to it in the future.





Something like this. In the first part, we prepared the data to form a tree using jsTree . Let's load the data (for those with a fine mental organization, it's better to move away from screens):





#  perl, js, html ...
# ?  .
sub make_tree {
    my $self = shift;
    my ( $attr, $id ) = @_;
    my $result = '';
    
    #      ,  
    #    JS 
    my %all;
    $all{core}{themes} = ( { variant => 'medium', responsive => 'true' } )
      if !$attr->{core}->{themes};
    $all{plugins} = ( $attr->{plugins} ) ? $attr->{plugins} : 'search';
    $all{search} =
      ( $attr->{search} )
      ? $attr->{search}
      : ( { case_insensitive => 'true', show_only_matches => 'false' } );
    
    #      
    %all = ( %all, %$attr );
    #  JSON
    my $DATA = JSON->new->indent->encode( \%all );
    # ,    
    #    json     
    $DATA =~ s/"false"/false/g;
    $DATA =~ s/"true"/true/g;
    $DATA =~ s/\"\*|\*\"/ /g;
    $DATA =~ s/"/'/g;

    #   (   
    #     )   DIV   
    $result .= qq{
    <link rel='stylesheet' href='/styles/lte_adm/plugins/jstree/themes/default/style.min.css' />
    <script type='text/javascript' src='/styles/lte_adm/plugins/jstree/jstree.min.js'></script>
    <div id='MY_TREE' align='left'></div>
  };
    #    js
    $result .= qq(
    <script>
      jQuery('#MY_TREE').jstree($DATA);
      </script>
   );

    #, ,  
    return $result;
}
      
      



Picture under the spoiler:





Oh yes, all this is drawn on the AdminLTE framework, in the default theme, hence the colors and icons. We do not pay attention to the "Modules" button, you will not have it.





What's next. Let's first remember how our mib browser will look like:





these are 2 functional and one information block:





  1. Directly the tree itself, with which we will work.





  2. A block of data returned by the device. Depending on the type of data, some manipulation can be performed.





  3. There will be detailed information about the selected identifiers.





We already have the tree. Let's draw an information block:





#  %lang   
sub nms_show {
    my ($attr) = @_;
    $snmpparms{UseSprintValue} = 1;

    #    API,      
    my $table = $html->table(
        {
            ID      => 'SNMP_SHOW',
            caption => $label,
        }
    );
    #   -,      
    $table->addrow( $html->b('objectID'),
        $SNMP::MIB{ $attr->{OID} }{objectID} );
    $table->addrow( $html->b( $lang{TYPE} ), $SNMP::MIB{ $attr->{OID} }{type} )
      if $SNMP::MIB{ $attr->{OID} }{type};
    $table->addrow( $html->b('Module'), $SNMP::MIB{ $attr->{OID} }{moduleID} );
    $table->addrow( $html->b('Varbinds'),
        "@{$SNMP::MIB{ $attr->{OID} }{varbinds}}" ) if $SNMP::MIB{ $attr->{OID} }{varbinds};;
    $table->addrow( $html->b( $lang{ACCESS} ),
        $SNMP::MIB{ $attr->{OID} }{access} );
    $table->addrow( $html->b('Syntax'), $SNMP::MIB{ $attr->{OID} }{syntax} )
      if $SNMP::MIB{ $attr->{OID} }{syntax};
    $table->addrow(
        $html->b( $lang{RANGE} ),
"$SNMP::MIB{$attr->{OID}}{ranges}[0]{low} .. $SNMP::MIB{$attr->{OID}}{ranges}[0]{high}"
    ) if $SNMP::MIB{ $attr->{OID} }{ranges}[0];
    $table->addrow( $html->b( $lang{DESCRIBE} ),
        $SNMP::MIB{ $attr->{OID} }{description} )
      if $SNMP::MIB{ $attr->{OID} }{description};
    $table->addrow( $html->b('Reference'),
        $SNMP::MIB{ $attr->{OID} }{reference} )
      if $SNMP::MIB{ $attr->{OID} }{reference};
    $table->addrow( $html->b('Index(es)'),
        "@{$SNMP::MIB{$attr->{OID}}{indexes}}" )
      if $SNMP::MIB{ $attr->{OID} }{indexes}[0];
    $table->addrow( $html->b('Value List'),
        oid_enums( $attr->{OID}, { STR => 1 } ) )
      if keys %{ $SNMP::MIB{ $attr->{OID} }{enums} };
    
    return $table->show();
}

#    enums
sub oid_enums {
    my ( $oid, $attr ) = @_;
    my %enums;
    my $str = '';
    foreach my $el ( keys %{ $SNMP::MIB{$oid}{enums} } ) {
        $enums{ $SNMP::MIB{$oid}{enums}{$el} } = $el;
    }
    if ($attr) {
        foreach my $key ( sort { $a <=> $b } keys %enums ) {
            $str .= "$key = $enums{$key} </br>";
        }
        return $str;
    }

    return %enums;
}
      
      



, 2- , . walk, get, gettable, snmpset. , :





#    snmpget
sub mibs_browser {

    my ($attr) = @_;
  
    if ( $FORM{OID} ) {
        #   
        print nms_show( { OID => $FORM{OID} } } );
        if ( $FORM{GET} ) {
            $snmpparms{UseSprintValue} = 1;
            # ,        IP 
            #      $obj
            my $sess = SNMP::Session->new( DestHost => $obj->{ip}, %snmpparms );
            my $iid = $attr->{IID} || 0;
            my $result = $sess->get( [ $FORM{OID}, $iid ] );
            #  
            if ( $sess->{ErrorNum} ) {
                    return $html->message( 'err', $lang{ERROR}, $sess->{ErrorStr} );
            }
            my $result_tbl = $html->table( {} );
            $result_tbl->addrow( $html->b( $lang{RESULT} ), $result );
            print $result_tbl->show();
            return 1;
        }
        elsif ( ... ) {
                #     
        }
        #
        return 1
    }
    #     2-  3- 
    my $res = $html->element('div', '', { id => 'RESULT'});
    #  
    my $tree = $html->element( 'div', mibs_tree());
    #       
    print $html->element( 'div', $tree . $res, { class => 'row' } );
    return 1;
}
      
      



'RESULT



' . . JavaScrpt - , , - , :





//$ID     ,
//     IP -
function renewLeftBox(itemName,Action,id,iid){
      iid = iid ? iid : 0 ;
      var url = 'index.cgi?OID=' + itemName + '&IID=' + iid + '&' + Action + '=$ID';
      jQuery('#RESULT').load(url);
    };

jQuery('#MY_TREE').on("changed.jstree", function (e, data) {
  renewLeftBox(data.instance.get_node(data.selected[0]).id,'SHOW', '$ID')
});

      
      



jsTree 'contextmenu'.



. JS:





//    
//     
function customMenu(node) {
          var items = {};
  //  ,    ,      
  //   
          if (node.type === 'scalar') {
            items.Get =  {
                  label: 'Get',
                  icon : 'fa fa-angle-down',
                  action: function () {
                    renewLeftBox(node.id,'GET');
                  }
            }        
          }
          if (node.type === 'row' || node.type === 'table' || node.type === 'indexes') {
            items.Walk = { 
                  label: 'Walk',
                  icon : 'fa fa-angle-double-down',
                  action: function () {
                    renewLeftBox(node.id,'WALK');
                  }
            }
          }
          if (node.type === 'table') {
            items.Table = { 
                  label: 'Table',
                  icon : 'fa fa-table',
                  action: function () {
                    renewLeftBox(node.id,'TABLE');
                  }
            }
          }

          return items;
      }
      
      



, , , . , , - , . , .








All Articles