Ad Widget

Collapse

Мониторинг ospf

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ktstyle
    Junior Member
    • Oct 2012
    • 6

    #1

    Мониторинг ospf

    Добрый день, Коллеги!

    Бьюсь уже третий день над проблемой мониторинга OSFP соседей через SNMP.
    Вся проблема заключается в том, что часть OID это адрес этого самого соседа и когда сосед пропадает, то есть по какой то причине OSPF падает. Этот сосед исчезает из списка и соовтественно из "живых" OID. Zabbix видя это, переводит ITEM в состояние Not supported. По какой то неведомой мне причине этоот статус ITEM мониторить тригером нельзя. Соответственно мы не увидим упал или нет сосед. Что очень печально.

    Есть ли у кого нибудь опыт настройки мониторинга OSPF?

    Я попробывал уже много вариантов, но пока ничего серьезного не нашел. Так понимаю можно сделать скрипт, который будет подключатся к роутеру и брать статуса соседа. Но это увеличит нагрузку на zabbix серьезно (много соседей и часто опрашивать) и у меня все не выходит собрать нормальный адекватный скрипт для этого.
  • Jimson
    Senior Member
    • Jan 2008
    • 1327

    #2
    не думаю что вы выбрали правильный способ мониторинга, но на тему пропадающих из SNMP итемов можно решить проблему через проксирование snmp + agentx расширение
    Code:
    #!/usr/bin/perl
    
    use feature 'switch';
    use strict;
    use warnings;
    use Getopt::Long qw( :config no_posix_default no_ignore_case bundling_override require_order );
    use POSIX qw( setsid );
    use Unix::Syslog qw( :subs :macros );
    use NetSNMP::OID;
    use NetSNMP::agent;
    use NetSNMP::ASN qw( ASN_COUNTER );
    use NetSNMP::default_store (':all');
    use NetSNMP::agent::default_store;
    use SNMP;
    
    $SNMP::auto_init_mib = 0;
    $SNMP::use_long_names = 1;
    $SNMP::use_numeric = 1;
    
    netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS, '/');
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
    netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION, 129);
    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
    
    my $agent = undef;
    my $running = 1;
    
    sub shutdown ();
    sub daemonize ();
    sub syserrors (;$);
    sub setstate ($$;@);
    sub usage (;$@);
    
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    my %opt = (
        ident           => 'agentx-fake-counter',
        pidfile         => '/var/run/agentx-fake-counter.pid',
        master          => '/var/agentx/master',
        nmsHost         => '172.17.11.1',
        nmsCommunity    => 'public'
    );
    
    GetOptions(
        \%opt,
        'ident|n=s',
        'pidfile|p=s',
        'master|m=s',
        'oid|o=s',
        'host|h=s',
        'community|c=s',
        'debug|d'
    ) or usage();
    
    daemonize() unless $opt{debug};
    
    my $rootOID = new NetSNMP::OID($opt{oid}) || usage "Can't parse OID:%s", $opt{oid};
    my %cache = ();
    
    syslog LOG_INFO, "Start OID %s host %s", $rootOID, $opt{host};
    setstate $rootOID, "";
    
    $SIG{'INT'}  = \&shutdown;
    $SIG{'QUIT'} = \&shutdown;
    $SIG{'TERM'} = \&shutdown;
    
    netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET, $opt{master});
    
    $agent = new NetSNMP::agent('Name' => $opt{ident}, 'AgentX' => 1);
    $agent->register($opt{ident}, $rootOID, \&agentxHandler);
    NetSNMP::agent::snmp_enable_syslog_ident($opt{ident}, LOG_LOCAL0) unless $opt{debug};
    
    my $counter = 0;
    while ($running) {
        $agent->agent_check_and_process(1);
        setstate $rootOID, "processed %u requests", $counter;
    }
    $agent->shutdown();
    unlink $opt{pidfile};
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    
    ############################################################################################
    # function agentxHandler()
    #   parameters:
    #               $handler
    #               $registration_info  object
    #               $request_info       object
    #               $requests           object
    #   return
    #               none
    #
    #   The handler subroutine will be called when a SNMP request received by
    # the agent for anything below the registered OID.
    #
    sub agentxHandler {
        my ($handler, $registration_info, $request_info, $requests) = @_;
        my ($request, $oid, $index, $sess, $vb, $value) = ();
        for ( $request = $requests; $request; $request = $request->next() ) {
            $oid = $request->getOID();
            $index = ($oid->to_array())[$oid->length() - 1] if $oid > $rootOID;
            if ( defined $index and $rootOID + $index == $oid or $rootOID == $oid ) {
                $sess = new SNMP::Session(
                    DestHost        => $opt{host},
                    Community       => $opt{community},
                    Version         => 2,
                    Retries         => 0,
                    Timeout         => 1000000
                );
                $vb = new SNMP::Varbind([$rootOID, $index]);
                if ( $request_info->getMode() == MODE_GET ) {
                    $value = $sess->get($vb);
                    if ( $sess->{ErrorNum} or $vb->type =~ /^NOSUCH/i ) {
                        if ( exists $cache{$oid} ) {
                            $request->setValue(ASN_COUNTER, $cache{$oid});
                        } elsif ( $sess->{ErrorNum} ) {
                            $request->setError($request_info, SNMP_ERR_GENERR);
                        }
                        next;
                    }
                } elsif ( $request_info->getMode() == MODE_GETNEXT ) {
                    $value = $sess->getnext($vb);
                    next if $sess->{ErrorNum} or $vb->type =~ /^NOSUCH/i;
                    $oid = new NetSNMP::OID( $vb->name );
                    next unless $rootOID + ($oid->to_array())[$oid->length() - 1] == $oid or $rootOID == $oid;
                    $request->setOID($oid);
                }
                $cache{$oid} = $value;
                $request->setValue(ASN_COUNTER, $value);
            } else {
                $request->setError($request_info, SNMP_ERR_NOSUCHNAME);
                syslog LOG_ERR, "Bad request OID:%s", $oid;
            }
            $counter++;
        }
    }
    
    ############################################################################################
    # function shutdown()
    #   parameters: none
    #   return:     none
    #
    sub shutdown () {
        $running = 0;
        syslog LOG_WARNING, "Got signal. Exiting.";
    }
    
    ############################################################################################
    # function daemonize()
    #   parameters: none
    #   return:     none
    #
    $SIG{CHLD} = 'IGNORE';
    sub daemonize () {
        chdir '/' or usage "Can't chdir to /: $!";
        open(STDIN, '/dev/null') or usage "Can't read /dev/null: $!";
        open(STDOUT, '>> /dev/null') or usage "Can't write to /dev/null: $!";
        defined(my $pid = fork) or usage "Can't fork: $!";
        if ($pid) {
            # parent
            open(PID, "> $opt{pidfile}") or usage "Couldn't open %s for writing: $!", $opt{pidfile};
            print PID "$pid\n" or usage "Couldn't write pid to %s: $!", $opt{pidfile};
            close(PID) or usage "Couldn't close %s: $!", $opt{pidfile};
            exit;
        }
        # child
        setsid() or usage "can't start a new session: $!";
        close(STDIN) or usage "Can't close STDIN: $!";
        close(STDOUT) or usage "Can't close STDOUT: $!";
        close(STDERR) or usage "Can't close STDERR: $!";
        openlog $opt{ident}, LOG_PID, LOG_LOCAL0;
    }
    
    ############################################################################################
    # function setstate()
    #   parameters:
    #               $status     string  описание состояние (что делаем)
    #               $msg        string  дополнительные данные в виде строки с макросами
    #               @params     array   парапетры подстановки в $msg
    #   return:
    #               none
    #
    #   Подмена отображения в списке процессов.
    #
    sub setstate ($$;@) {
        $0 = sprintf("%s: %s [%s]", $opt{ident}, shift, sprintf(shift, @_));
    }
    
    ############################################################################################
    # function usage()
    #   parameters:
    #               $msg        string  строка с макросами sprintf(3)
    #               @params     array   список параметров для подстановки в $msg
    #   return:
    #               none
    #
    #   Вывод ругани в STDERR и аварийное завершение скрипта.
    #
    sub usage (;$@) {
        my ($msg, @params) = @_;
        print STDERR sprintf($msg, @params) . "\n" if $msg;
        print STDERR "Who are you? Goodbye!\n";
        exit 1;
    }
    с конфигурацией snmpd сами разберетесь по идее

    P.S. оптимизировать скрипт не советую, net-snmp глюкав чуть более чем полностью, например, если создать udp сокет глобально и попытаться им пользоваться в хендлере то буквально через десяток запросов snmpd виснет
    Last edited by Jimson; 25-10-2013, 22:05.

    Comment

    • ktstyle
      Junior Member
      • Oct 2012
      • 6

      #3
      Originally posted by Jimson
      не думаю что вы выбрали правильный способ мониторинга, но на тему пропадающих из SNMP итемов можно решить проблему через проксирование snmp + agentx расширение

      ....

      с конфигурацией snmpd сами разберетесь по идее

      P.S. оптимизировать скрипт не советую, net-snmp глюкав чуть более чем полностью, например, если создать udp сокет глобально и попытаться им пользоваться в хендлере то буквально через десяток запросов snmpd виснет
      Спасибо! Попробую имплатировать. Правда, связка "snmp + agentx" для меня пока мрак. Буду отуплять.

      Comment

      Working...