作成したエージェントの組込方法
7.7 拡張MIBに対応するエージェントの作成
net-snmpの場合、ソースファイルからエージェントを作成するには3つの方法があります。この章ではそれぞれの方法を解説し、個人的な感想を付加しています。
7.7.1 snmpd自体に組み込み、snmpdを再構築
エージェント用ソースファイルをsnmpd
に読み込ませ、snmpd
自体を再構築(つまり再コンパイル)する方法です。ソースファイルが1個の場合と複数個の場合で方法が違います。今回、私はエージェント用ソースファイルは2個(matsu_object.c, matsu_trap.c)あります。しかし複数個の場合でうまく動かなかったので、今回は一つの場合で構築します。
下記のようにソースを手作業でマージします。
- matsu_object.c, matsu_trap.c -> matsutest.c
- matsu_object.h, matsu_trap.h -> matsutest.h
上記の準備ができたら、snmpd
を止め、所定の場所にソースファイルとヘッダーファイルを置きます。
% /etc/init.d/snmpd stop % cp -p matsutest.* ~/.snmp/net-snmp-5.4.1.2/agent/mibgroup
configureを実行し、Makefileを作成します。
% cd ~/.snmp/net-snmp-5.4.1.2 % ./configure --prefix=/usr --with-mib-modules=matsutest
Makefileを実行、作成したsnmpd
をインストールします。
% make % make install
snmpd
を走らせます。
% /etc/init.d/snmpd start % snmpwalk -v 2c -c localcom localhost MATSU-TEST-MIB::matsutest MATSU-TEST-MIB::mtuObject1.0 = STRING: matsutest1, pid:[24306] timer:OFF:[0] call_count:[1] MATSU-TEST-MIB::mtuObject2.0 = INTEGER: 1 MATSU-TEST-MIB::mtuTrap.0 = INTEGER: off(0) MATSU-TEST-MIB::mtuTimer.0 = INTEGER: off(0) %
手順としてはconfigure
コマンドを実行する際に、ソースファイルをパラメータとして渡し、作成されたMakefileを使ってsnmpd
を再構築します。これ以降でソースファイルを修正した場合は、make
から実行します。
この方法は、そもそもsnmpd
をソースファイルからsnmp
環境を構築した場合にのみ可能な方法で(まさに今回当レポートがそうなんですが)、パッケージからインストールした環境では使えません。
また、エージェントの開発中はソースファイルを頻繁に手直しするもんです。その度にsnmpd
を止めてmake install
するのは、はっきりいって面倒です。make install
は以外と時間がかかりますし。
という訳で、個人的にはこの方法はほとんど使ったことがありません。
7.7.2 共有ライブラリを作成し、snmpd実行時に動的リンク
エージェント用ソースファイルを元に共有ライブラリを作成、それをsnmpd実行時にリンクさせて実行します。共有ライブラリを作成するためのMakefileが必要です。
CC=gcc OBJS=matsu_object.o matsu_trap.o TARGETS=matsu_test.so CFLAGS=-I. `net-snmp-config --cflags` -fPIC -shared BUILDLIBS=`net-snmp-config --libs` BUILDAGENTLIBS=`net-snmp-config --agent-libs` all: $(TARGETS) $(TARGETS): $(OBJS) $(CC) $(CFLAGS) -o $(TARGETS) $(OBJS) clean: rm $(OBJS) $(TARGETS)
snmpd
を止め、上記Makefileとダウンロード先にあるmatsutest.c、matsutest.hをエージェント開発場所に置いてmake
を実行、共有ライブラリを作ります。
以下のオペレーションでは、エージェント用ファイル置き場を/root/agent_sample、エージェント用共有ライブラリをmatsu_test.soとしています。
% /etc/init.d/snmpd stop % cd /root/agent_sample % make -f make_lib
共有ライブラリを動的に読み込む設定で起動します。
% snmpd -L -Dmatsu_test,dlmod -Ls6 -Lf /dev/null -p /var/run/snmpd.pid -a
snmpset
を実行して、共有ライブラリ設定用MIBに対しライブラリを設定、読み込ませます。
% snmpset -v 2c -c securecom 192.168.1.12 UCD-DLMOD-MIB::dlmodStatus.1 i create UCD-DLMOD-MIB::dlmodStatus.1 = INTEGER: create(6) % snmpset -v 2c -c securecom 192.168.1.12 UCD-DLMOD-MIB::dlmodName.1 s "matsutest" UCD-DLMOD-MIB::dlmodPath.1 s "/root/agent_sample/matsu_test.so" UCD-DLMOD-MIB::dlmodName.1 = STRING: matsutest UCD-DLMOD-MIB::dlmodPath.1 = STRING: /root/agent_sample/matsu_test.so % snmpset -v 2c -c securecom 192.168.1.12 UCD-DLMOD-MIB::dlmodStatus.1 i load UCD-DLMOD-MIB::dlmodStatus.1 = INTEGER: load(4)
実行すると、値が取得できます。
% snmpwalk -v 2c -c localcom localhost MATSU-TEST-MIB::matsutest MATSU-TEST-MIB::mtuObject1.0 = STRING: matsutest1, pid:[24615] timer:OFF:[0] call_count:[1] MATSU-TEST-MIB::mtuObject2.0 = INTEGER: 1 MATSU-TEST-MIB::mtuTrap.0 = INTEGER: off(0) MATSU-TEST-MIB::mtuTimer.0 = INTEGER: off(0) %
こちらの方法は、snmpd
本体を拡張するよりもずっと汎用的であると思われます。ただ、実行する際にいちいちsnmpset
を実行したり、snmpd
を開始する際に共有ライブラリを指定するのも、やや煩雑であり、環境依存の要因になりかねません。
という訳で、7.7.1よりもずっと良い方法なんですが、やっぱりこの方法は使ったことがありません(実は今回初めて使いました)。
7.7.3 agentxのサブエージェントとして構築
エージェント用ソースファイルを基に実行ファイルを作成、それをsnmpd
が用意したエージェント用ソケットを通して実行します。実行ファイルを作るのでmain
関数が必要で、かつMakefileが必要です。
CC=gcc OBJS=main.o matsu_object.o matsu_trap.o TARGETS=matsu_test CFLAGS=-I. `net-snmp-config --cflags` BUILDLIBS=`net-snmp-config --libs` BUILDAGENTLIBS=`net-snmp-config --agent-libs` all: $(TARGETS) $(TARGETS): $(OBJS) $(CC) -o $(TARGETS) $(OBJS) $(BUILDAGENTLIBS) clean: rm $(OBJS) $(TARGETS)
main.cは作ってもらう方法もありますが、うまくいかなかったので今回は自作しています(net-snmpのチュートリアルを参考にしています)。
上記Makefileおよびダウンロード先にあるmain.cをエージェント開発場所に置いてmakeを実行、実行ファイルを作ります。
なお、作成された実行ファイルを今後は「サブエージェント」と呼びます。
% cd <エージェント用ファイル置き場> % make -f make_file
snmpd.conf に、下記を追記します。
% vi /usr/share/snmp/snmpd.conf master agentx <- ファイルの最後に追記
今回はsnmpd
をソースファイルから構築しているため、agent用ソケット置き場が作成されていません。下記のコマンドを実行し、場所を作成します(既に/var/agentxが存在している場合は結構です)。
% mkdir /var/agentx
snmpd
を再起動します。
% /etc/init.d/snmpd restart
サブエージェントを起動し、snmpwalk
などを実行すると値が取得できることを確認できます。
% ./matsu_test netsnmp_assert !"registration != duplicate" failed agent_registry.c:535 netsnmp_subtree_load() netsnmp_assert !"registration != duplicate" failed agent_registry.c:535 netsnmp_subtree_load() netsnmp_assert !"registration != duplicate" failed agent_registry.c:535 netsnmp_subtree_load() NET-SNMP version 5.4.1.2 AgentX subagent connected matsutest is up and running. % snmpwalk -v 2c -c localcom localhost MATSU-TEST-MIB::matsutest MATSU-TEST-MIB::mtuObject1.0 = STRING: matsutest1, pid:[24899] timer:OFF:[0] call_count:[1] MATSU-TEST-MIB::mtuObject2.0 = INTEGER: 2 MATSU-TEST-MIB::mtuTrap.0 = INTEGER: off(0) MATSU-TEST-MIB::mtuTimer.0 = INTEGER: off(0) %
こちらの方法は、Makefileの用意や自作でmain
関数を作成する場合があるなど準備が煩雑ですが、それでもかなり汎用的であると思われます。
snmpd
への設定もsnmpd.confに1行追加で済みますし、snmpd
を落とさずにサブエージェントだけを再起動することが可能なので、サブエージェントの開発や試験が容易です。
という訳で、私の場合、エージェント開発ではサブエージェントばかり使ってます。
尚、上記でmatsu_testを実行する際にassertが出力されますが、動作に影響を与えるものではありません。しかし気持ち悪い。
次回は上記assertが出ないよう、snmpdにパッチを当てる手順について説明させて頂きます。