Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

21.7.5.2. Perl による Net-SNMP の拡張

extend ディレクティブを使用したシェルスクリプトの実行は、S N M P でカスタムアプリケーションメトリクスを公開する非常に限定的な方法です。Net-SNMP エージェントは、カスタムオブジェクトを公開するための埋め込み Perl インターフェースも提供します。Optional チャンネルの net-snmp-perl パッケージは、Red Hat Enterprise Linux で組み込み Perl プラグインの作成に使用される NetSNMP::agent Perl モジュールを提供します。

注記

Optional および Supplementary チャンネルをサブスクライブする前に、「対象範囲の詳細」を参照してください。これらのチャンネルからパッケージをインストールする場合は、Red Hat カスタマーポータルの記事「証明書ベースの管理を使用して、Optional および Supplementary チャンネル、-devel パッケージにアクセスする方法」で説明されている手順を行ってください。

NetSNMP::agent Perl モジュールは、エージェントの OID ツリーの一部に対する要求を処理するために使用される agent オブジェクトを提供します。agent オブジェクトのコンストラクターには、エージェントを snmpd のサブエージェントまたはスタンドアロンエージェントとして実行するためのオプションがあります。埋め込みエージェントを作成するために必要な引数はありません。

use NetSNMP::agent (':all');

my $agent = new NetSNMP::agent();

agent オブジェクトには、コールバック関数を特定の OID に登録するために使用される register メソッドがあります。register 関数は、名前、OID、コールバック関数へのポインターを取ります。以下の例は、hello_handler と呼ばれるコールバック関数を OID .1.3.6.1.4.1.8072.9999.9999 で要求を処理する SNMP Agent に登録しています:

$agent->register("hello_world", ".1.3.6.1.4.1.8072.9999.9999",
         \&hello_handler);
注記

通常、OID .1.3.6.1.4.1.8072.9999.9999 (NET-SNMP-MIB::netSnmpPlaypen) は表示目的のみに使用されます。お客様の組織に root OID がない場合は、ISO Name Registration Authority (米国では ANSI) にご連絡いただくと取得できます。

ハンドラー関数は、HANDLERREGISTRATION_INFOREQUEST_INFOREQUESTS の 4 つのパラメーターで呼び出されます。REQUESTS パラメーターには、現在の呼び出しの要求一覧が含まれており、反復されデータが追加されるはずです。一覧の request オブジェクトには get 及び set メソッドがあるため、要求の OIDvalue を操作することができます。例として、以下の呼び出しは「hello world」という文字列に要求オブジェクトの値を設定します。

$request->setValue(ASN_OCTET_STR, "hello world");

ハンドラー関数は、GET 要求と GETNEXT 要求という 2 種類の SNMP 要求に応答できます。要求のタイプは、ハンドラー関数に第 3 のパラメーターとして渡される request_info オブジェクトの getMode メソッドを呼び出すことによって、決定されます。要求が GET 要求である場合、呼び出し元は、ハンドラーに要求の OID に応じて request オブジェクトの value を設定するよう求めます。要求が GETNEXT 要求である場合、呼び出し元は、ハンドラーに要求の OID をツリー内で次に利用可能な OID に設定するよう求めます。以下のコードは、この例を示しています。

my $request;
my $string_value = "hello world";
my $integer_value = "8675309";

for($request = $requests; $request; $request = $request->next()) {
 my $oid = $request->getOID();
 if ($request_info->getMode() == MODE_GET) {
  if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
   $request->setValue(ASN_OCTET_STR, $string_value);
  }
  elsif ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.1")) {
   $request->setValue(ASN_INTEGER, $integer_value);
  }
 } elsif ($request_info->getMode() == MODE_GETNEXT) {
  if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
   $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.1");
   $request->setValue(ASN_INTEGER, $integer_value);
  }
  elsif ($oid < new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
   $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.0");
   $request->setValue(ASN_OCTET_STR, $string_value);
  }
 }
}

getModeMODE_GET を返す場合、ハンドラーは request オブジェクトの getOID 呼び出しの値を分析します。requestvalue は、OID が .1.0 で終わる場合は string_value に、OID が .1.1 で終わる場合は integer_value に設定されます。getModeMODE_GETNEXT を返す場合、ハンドラーは要求の OID が .1.0 かどうかを見つけ出し、その後 .1.1 に対する OID と値を設定します。ツリーで要求が .1.0 より高い場合は、.1.0 に対する OID と値が設定されます。実際、これはツリーの次の値を返すため、snmpwalk のようなプログラムは構造に関する事前知識なくツリーをトラバースできます。

変数のタイプは NetSNMP::ASN からの定数を使用して設定されます。利用可能な定数の全一覧については、NetSNMP::ASNperldoc を参照して下さい。

この例の Perl プラグインのコード全一覧は、以下のとおりです:

#!/usr/bin/perl

use NetSNMP::agent (':all');
use NetSNMP::ASN qw(ASN_OCTET_STR ASN_INTEGER);

sub hello_handler {
 my ($handler, $registration_info, $request_info, $requests) = @_;
 my $request;
 my $string_value = "hello world";
 my $integer_value = "8675309";

 for($request = $requests; $request; $request = $request->next()) {
  my $oid = $request->getOID();
  if ($request_info->getMode() == MODE_GET) {
   if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
    $request->setValue(ASN_OCTET_STR, $string_value);
   }
   elsif ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.1")) {
    $request->setValue(ASN_INTEGER, $integer_value);
   }
  } elsif ($request_info->getMode() == MODE_GETNEXT) {
   if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
    $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.1");
    $request->setValue(ASN_INTEGER, $integer_value);
   }
   elsif ($oid < new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.1.0")) {
    $request->setOID(".1.3.6.1.4.1.8072.9999.9999.1.0");
    $request->setValue(ASN_OCTET_STR, $string_value);
   }
  }
 }
}

my $agent = new NetSNMP::agent();
$agent->register("hello_world", ".1.3.6.1.4.1.8072.9999.9999",
         \&hello_handler);

プラグインをテストするには、上記のプログラムを /usr/share/snmp/hello_world.pl にコピーして、以下の行を /etc/snmp/snmpd.conf の設定ファイルに追加して下さい:

perl do "/usr/share/snmp/hello_world.pl"

新しい Perl プラグインをロードするためには、SNMP Agent Daemon を再起動する必要があります。再起動すると、snmpwalk は新しいデータを返すはずです。

~]$ snmpwalk localhost NET-SNMP-MIB::netSnmpPlaypen
NET-SNMP-MIB::netSnmpPlaypen.1.0 = STRING: "hello world"
NET-SNMP-MIB::netSnmpPlaypen.1.1 = INTEGER: 8675309

snmpget を使用すると、ハンドラーの他のモードを使用することも可能です:

~]$ snmpget localhost \
  NET-SNMP-MIB::netSnmpPlaypen.1.0 \
  NET-SNMP-MIB::netSnmpPlaypen.1.1
NET-SNMP-MIB::netSnmpPlaypen.1.0 = STRING: "hello world"
NET-SNMP-MIB::netSnmpPlaypen.1.1 = INTEGER: 8675309