Получение обновлений для рабочих мест в локальной сети (продолжение мысли)

Ранее я уже начинал рассматривать данную тему. Но сегодня мне бы хотелось продолжить повествование об изыскании в этом направлении.

Если вы помните, в указанной выше статье, для получения информации об установленных пакетах на целевой машине использовалось копирование архива, содержащего в себе копию директории /var/lib/rpm на сетевой диск сервера. Далее сервер использовал данный архив для поиска обновлений используемых пакетов.
В этой статье я хочу рассмотреть данный шаг с другой стороны, а именно получение информации об используемых пакетов через службу SNMP.
Почему я решил попробовать SNMP для данной задачи? Наверно потому, что я еще не разбирался с SNMP в области предоставления данных. Это мой первый опыт, поэтому данная статья скорее всего будет содержать в себе не эффективные методы и способы сбора и предоставления информации. Приступим к рассмотрению.

Вводные данные.

  1. Первым делом для использования на целевой машине агента snmp, необходимо установить сам snmp: urpmi net-snmp.
  2. После установки данной службы необходимо её настроить. Минимальные настройки, достаточные для запуска службы
    cat /etc/snmp/snmpd.conf
    
    syslocation  "BDag host"
    syscontact  “BDag <bdag@localhost>”
    rocommunity  public 127.0.0.1
    
  3. Так же необходимо наличие установленных пакетов, скорее всего они уже установлены, perl, perl-NetSNMP

Реализация идеи.

После прочтения документации по созданию SNMP агентов и просмотра неодного примера реализации, был модифицирован perl скрипт из примеров, для интеграции его в snmp как агента.

use NetSNMP::OID (':all');
use NetSNMP::agent (':all');
use NetSNMP::ASN (':all');
use URPM;

$program = "BDAG_test_mod";

print STDERR "BDAG test SNMP module v.0.1\nDebug mode is on.\n" if ($debugging);

sub help {
        my ($message) = @_;
        print STDERR '
ERROR: ' .  $program . ':' . $message .
'

Here is some help ...

        This program should be started from snmpd.conf.

        An example for allowing one to walk /etc/passwd would be when this program is /etc/snmp/snmpagent.pl:
                perl print STDERR \'Perl extentsions:\' . \n\"
                perl $debugging = \'1\';
                perl {$regat = '.1.3.6.1.4.1.8072.999'; $extension='1'; do '/etc/snmp/snmpagent.pl'; }


        Use snmpd -f to see what is going on.


        The result of a snmpwalk would be:
                NET-SNMP-MIB::netSnmp.999.1.1.1 = STRING: "value1"
                NET-SNMP-MIB::netSnmp.999.1.1.2 = STRING: "value2"
                NET-SNMP-MIB::netSnmp.999.1.1.1 = STRING: "value3"
                NET-SNMP-MIB::netSnmp.999.1.1.1 = STRING: "value4"

        NB: snmptable requires a MIB to work.

        Owen Brotherwood, DK 2007, modifed BDag
        GNU General Public License V3
';
        die($message);
}

if (!defined($regat)) {
        help('No $regat defined');
}

    #
    # Handler routine to deal with SNMP requests
    #
open(PRODID,'/etc/product.id');
         my $productid = <PRODID>;
close(PRODID);

chomp($productid);
my @elm=split(',',$productid);
my %product={};
foreach (@elm) {
    my @param = split('=',$_);
    $product{$param[0]}=$param[1];
}


sub myhandler {
    my  ($handler, $registration_info, $request_info, $requests) = @_;
    my $request;
    my %my_oid = ();
    my $ASN_OCTET_STR = 4;
    my $delimT = '';
    my $delimV = ':';

    my $db = URPM::DB::open();
    undef(@mibdata);
    push(@mibdata,lc($product{'vendor'}).':'.lc($product{'branch'}).':'.lc($product{'version'}).':'.lc($product{'arch'}));

    $db->traverse(sub {
        my ($package) = @_; # this is a URPM::Package object
        $pkg=$package->name.":".$package->version.":".$package->release;
        push(@mibdata,$pkg);
        }
    );

    $base_oid = new NetSNMP::OID($regat . '.' . $extension);
    undef($prev_oid);
    $jndex = 1;


    foreach $line (@mibdata) {
                chomp $line;
                if ($delimT != ''){
                        ($index_name, $index_type, $index_values) = split(/$delimT/, $line);
                }else{
                        $index_values = $line;
                        $index_name = 'Unknown';
                        $index_type = $ASN_OCTET_STR;
                }
                my @value = split(/$delimV/, $index_values);
                my $index = 1;
                foreach $mibit (@value) {
                        $this_oid = new NetSNMP::OID($base_oid . '.' . $jndex . '.' . $index);
                        $oid_type{$this_oid} = $index_type;
                        $oid_value{$this_oid} = $mibit;
                        $oid_index{$this_oid} = $index;
                        $oid_jndex{$this_oid} = $jndex;
                        if (defined($prev_oid)){
                                $oid_next{$prev_oid} = $this_oid;
                        }
                        $prev_oid = $this_oid;
                        print STDERR "Loading $this_oid $oid_type{$this_oid}::$oid_value{$this_oid}  \n" if ($debugging);
                        $index++;
                }
                $jndex++;
        }

        $mjndex = $jndex;
        $mindex = $index;
        for ($jndex = 1; $jndex < $mjndex; $jndex++) {
                $this_oid = new NetSNMP::OID($base_oid . '.' . $jndex);
                $next_oid = new NetSNMP::OID($this_oid . '.1');
                $oid_next{$this_oid} = $next_oid;
        }

    for ($request = $requests; $request; $request = $request->next()) {
        #
        #  Work through the list of varbinds
        #
        my $oid = $request->getOID();

        print STDERR "$program @ $oid \n" if ($debugging);

        if ($request_info->getMode() == MODE_GET) {
        print STDERR "GET" if ($debugging);
        if (exists $oid_value{$oid}) {
            print STDERR "->$oid_value{$oid}\n" if ($debugging);
            $request->setValue($oid_type{$oid}, $oid_value{$oid});
        }else{
            print STDERR " No value ...\n";
        }


        }elsif ($request_info->getMode() == MODE_GETNEXT) {
# long way to walk
                        print STDERR " GETNEXT " if($debugging);
                        if (defined($oid_next{$oid})) {
                                $next_oid = $oid_next{$oid};
                                $type_oid = $oid_type{$next_oid};
                                $value_oid = $oid_value{$next_oid};
                                $request->setOID($next_oid);
                                $request->setValue($type_oid, $value_oid);
                        }elsif ($oid <= $base_oid) {
                                $next_oid = new NetSNMP::OID($base_oid . '.1.1');
                                $type_oid = $oid_type{$next_oid};
                                $value_oid = $oid_value{$next_oid};
                                $request->setOID($next_oid);
                                $request->setValue($type_oid, $value_oid);
                        }else{
                                print STDERR "Hit by a truck whilst walking ...\n" if ($debugging);
                        }
                }
    }
    }



{
        if (!$agent) {
               help('No $agent defined');
        }

        print STDERR "$program @ $regat \n";

        my $regoid = new NetSNMP::OID($regat);

        $agent->register($program, $regoid, \&myhandler);
        print STDERR $program . " Agent is started.\n";
}


Данный скрипт сохраняем в директорию /etc/snmp, ну или по вашему желанию. А затем подключаем его в конфигурационном файле /etc/snmp/snmpd.conf
perl $debugging='0';
perl {$regat = '.1.3.6.1.4.1.8072.999'; $extension='1'; do '/etc/snmp/snmpagent.pl'; }


Для того чтобы проверить, все ли работает, достаточно запустить службу:
snmpd -f
и в другой консоли обратимся с запросом к агенту:
snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.4.1.8072.999


Результат выполнения данной команды должен быть список:
NET-SNMP-MIB::netSnmp.999.1.1.1 = STRING: «mandriva»
NET-SNMP-MIB::netSnmp.999.1.1.2 = STRING: «devel»
NET-SNMP-MIB::netSnmp.999.1.1.3 = STRING: «2011.0»
NET-SNMP-MIB::netSnmp.999.1.1.4 = STRING: «x86_64»
NET-SNMP-MIB::netSnmp.999.1.2.1 = STRING: «lib64kopeteidentity1»
NET-SNMP-MIB::netSnmp.999.1.2.2 = STRING: «4.5.80»
NET-SNMP-MIB::netSnmp.999.1.2.3 = STRING: «1mdv2011.0»
NET-SNMP-MIB::netSnmp.999.1.3.1 = STRING: «lib64nepomuktasks0»



Используемая литература:
  1. Extending snmpd using perl
  2. man:URPM

PS: Информацию передает довольно медленно, при этом наблюдается сильная нагрузка на процессор. В связи с этим, если кто знает как данную проблему решить прошу сообщить.
С передачей данных через SNMP работаю впервые, поэтому алгоритмы могут быть не эффективны, приветствуются любые дополнения и комментарии по данной теме.
Опубликовать в своем блоге livejournal.com

Комментарии Вконтакте facebook

Комментарии (0)

rss свернуть / развернуть
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.
Блоги, Полезные советы и секреты, Получение обновлений для рабочих мест в локальной сети (продолжение мысли)