2011年05月27日
実践SNMP+Java MIBテーブルのフェッチ(TableUtils)
MIBテーブルとはデータベースのテーブルと同様に行と列で管理されたMIBオブジェクトの集まりです。
MIBテーブルを理解するにはMIBブラウザを使って視覚的に捉えることも重要です。ここではiREASONING社のMIBブラウザ(無料)を使って説明します。
これを見ると、ifTableにはifIndex, ifDescr, ifTypeなどがエントリされており、テーブルのインデックスはifIndexであることがわかります(鍵のアイコンになっています)。もちろん、MIBファイルを直接確認しても良いでしょう。
ifEntry OBJECT-TYPESYNTAX IfEntryACCESS not-accessibleSTATUS mandatoryDESCRIPTION"An interface entry containing objects at thesubnetwork layer and below for a particularinterface."INDEX { ifIndex }
このようにMIBテーブルには必ず行を特定する為のIndexが定義されており、この値を使って各OIDのインスタンスを指し示す事が出来ます(例:ifDescr.1)。尚、テーブルによっては複合indexの場合もあります。
早速、SNMP4Jを使ってifTableの値を幾つかフェッチしてみましょう。
Javaコード
public void getTable() throws IOException { String host = "localhost"; //host = "192.168.10.1"; int port = 161; String community = "public"; String[] oids = { ".1.3.6.1.2.1.2.2.1.1", // ifIndex ".1.3.6.1.2.1.2.2.1.2", // ifType ".1.3.6.1.2.1.2.2.1.3", // ifMtu ".1.3.6.1.2.1.2.2.1.4", // ifSpeed ".1.3.6.1.2.1.2.2.1.5" // ifPhysAddress }; Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); snmp.listen(); CommunityTarget comTgt = new CommunityTarget(); comTgt.setAddress(new UdpAddress(host+"/"+port)); comTgt.setCommunity(new OctetString(community)); // snmp community. comTgt.setVersion(SnmpConstants.version2c); TableUtils table = new TableUtils(snmp, new DefaultPDUFactory()); OID[] columnOIDs = new OID[oids.length]; for (int i=0; i<oids.length; i++) { columnOIDs[i] = new OID(oids[i]); } OID lowerBoundIndex = null; //new OID("1"); OID upperBoundIndex = null; // getTable params. // Target target, OID[] columnOIDs, OID lowerBoundIndex, OID upperBoundIndex List result = table.getTable( comTgt, columnOIDs, lowerBoundIndex, upperBoundIndex); for (int i=0; i<result.size(); i++) { TableEvent event = (TableEvent) result.get(i); /* * org.snmp4j.util.RetrievalEvent * public static final int STATUS_EXCEPTION -4 * public static final int STATUS_OK 0 * public static final int STATUS_REPORT -3 * public static final int STATUS_TIMEOUT -1 * public static final int STATUS_WRONG_ORDER -2 */ int status = event.getStatus(); if (status == RetrievalEvent.STATUS_OK) { VariableBinding[] vbs = event.getColumns(); System.out.print("table index:"+event.getIndex().toString()+"¥t -> "); for (int j=0; j<vbs.length; j++) { VariableBinding vb = vbs[j]; System.out.print( //vb.getOid()+"->"+ vb.getVariable()+"¥t"); } } System.out.println(); } snmp.close(); // close local udp port and response dispacher. }
実行結果(サンプル)
table index:1 -> 1 lo0 24 16384 0
table index:2 -> 2 gif0 55 1280 0
table index:3 -> 3 stf0 57 1280 0
table index:4 -> 4 en0 6 1500 1000000000
table index:5 -> 5 en1 6 1500 10000000
table index:6 -> 6 fw0 144 4078 10000000
説明
7~13行目でifTableから取得するOIDの配列(ifIndex~ifPhysAddress)を定義しています。
22行目でテーブルのフェッチに利用するTabaleUtilsクラスのインスタンスを生成し、33行目でgetTableメソッドを呼出し、フェッチを実行しています。
ポーリング結果は、行に相当するTableEventインスタンスのListとして戻ります。この値を36行目以降で取り出しています。もし、OIDも合わせて確認したい場合、53行目のコメントを外してください。
TableEventクラスの面白い(便利な)ところはgetIndexメソッドでテーブルのインデックスを取得出来るところです。このIndexを取り出すという作業は大して難しい事では無く、VariableBinding::getOidメソッドの戻り値であるOIDインスタンスの値を分解すれば良いのですが、SNMP4J(API)側で提供してくれるとコード量も減って便利です。試しに複合Indexを持つipNetToMediaTableもフェッチしてみましょう。
実行結果は次の通りです。
table index:5.192.168.0.1 -> 00:a0:de:36:ff:30 1
table index:5.192.168.0.12 -> 90:27:e4:3a:57:69 1
table index:5.192.168.0.14 -> 00:1a:a0:90:17:81 1
table index:5.192.168.0.25 -> cc:08:e0:c9:f8:da 1
table index:5.192.168.0.30 -> 00:21:70:33:15:e3 1
table index:5.192.168.0.132 -> 00:0c:29:bd:1b:07 1
table index:5.192.168.0.135 -> 00:0c:29:d6:a4:89 1
複合indexでも問題ありませんね(難しい処理では無いので当然なのですが)。
最後にTableUtils::getTableメソッドの引数であるlowerBoundIndex、upperBoundIndexについて説明します。これは開始、終了行のインデックスを使い、フェッチ範囲を指定する為のオプションです。もし、29行目のlowerBoundIndexを new OID("1") とすると、実行結果は次のようになります。
table index:2 -> 2 gif0 55 1280 0
table index:3 -> 3 stf0 57 1280 0
table index:4 -> 4 en0 6 1500 1000000000
table index:5 -> 5 en1 6 1500 10000000
table index:6 -> 6 fw0 144 4078 10000000
index:1の行が無くなっていますね。つまりlowerBoundIndexを指定するとそれ以降のインデックス持つ行のみ取得します。upperBoundIndexはこの逆です。
実践で使えるか?
僕自身はTableUtilsクラスを利用していないので何とも言えません。僕の場合、より細かなチューニングが出来るよう、GetNext/GetBulkを組み合わせた独自クラスを用意しMIBテーブルをフィッチしています。
TableUtilsクラスはHight Level APIと言われる、ある程度の処理までをAPI側で隠蔽してくれる便利なクラスですが、その反面チューニングが難しい、SNMP4J APIに依存したアプリケーションになる、というリスクもあります。
複雑・巨大なテーブルはフェッチしない、SNMP4Jに依存しても問題無い、という方は是非どうぞ。
オライリー・ジャパン
売り上げランキング: 49043
技術評論社
売り上げランキング: 18925