RubyのSNMPライブラリでプライベートMIBを取り扱う方法を紹介します。
SNMPのオブジェクトID(OID)からオブジェクト名へ変換や、オブジェクト名からOIDに変換ができます。
SNMPのOIDばかりだと混乱してしまうため、積極的にオブジェクト名を使いましょう。
環境
- Ubuntu 14.04
- Ruby 2.2.4
- snmp 1.2.0
- smitools 0.4.8 - smidumpコマンド、MIBからOIDを抜き出すために必要
インストール
Ubuntuの場合は、apt-getでsmitoolsをインストールします。
必要なGemも合わせてインストールします。
$ sudo apt-get install smitools
$ gem install snmp
プライベートMIBのダウンロード
今回は例としてCiscoのプライベートMIBであるCISCO-PING-MIBを取り扱います。必要なプライベートMIBをCisco SNMP オブジェクトナビゲータからダウンロードします。依存関係があるため、下記の3つのMIBをダウンロードします。
- CISCO-SMI
- CISCO-TC
- CISCO-PING-MIB
カレントディレクトリにmibsというディレクトリを作成し、上記のプライベートMIBを保存します。
$ ls -l ./mibs/
合計 140
-rw-r--r-- 1 kooshin kooshin 16208 2月 7 18:00 CISCO-PING-MIB
-rw-r--r-- 1 kooshin kooshin 16397 2月 7 18:00 CISCO-SMI
-rw-r--r-- 1 kooshin kooshin 102591 2月 7 18:00 CISCO-TC
プライベートMIBの変換
snmpライブラリで取り扱うため、MIBファイルからOIDファイルに変換します。
./mibs/に保存したMIBを変換し、OIDとオブジェクト名が対となったYAMLファイルを作成します。この作業は一度きりのため、irbで変換します。
SNMP::MIB.import_moduleのクラスメソッドで変換します。内部の処理でsmidumpコマンドを呼び出しているため、引数などはそのまま使えます。
今回はCISCO-SMIファイルとCISCO-TCファイルが依存関係としてあるため、-p
オプションで依存ファイルを指定し、最後に変換対象のCISCO-PING-MIBファイルを指定しています。
SNMP::MIB.import_moduleの実行時にエラーメッセージがなく、モジュール名が返ってくればOKです。
$ irb
irb(main):001:0> require 'snmp'
=> true
irb(main):002:0> SNMP::MIB.import_module('-p mibs/CISCO-SMI -p mibs/CISCO-TC mibs/CISCO-PING-MIB', './mibs')
=> "CISCO-PING-MIB"
irb(main):003:0>
下記のように「smidump: module `*' contains errors, expect flawed」のエラーが返って来た場合は、依存関係があるにも関わらず、依存ファイルが指定されていない可能性があります。このエラーメッセージが表示されても、YAMLファイルが作成されますが、OIDが欠落して使えない可能性があります。
irb(main):002:0> SNMP::MIB.import_module('mibs/CISCO-TC', './mibs')
smidump: module `mibs/CISCO-TC' contains errors, expect flawed output
=> "CISCO-TC"
SNMP::MIB.import_moduleの実行が成功するとCISCO-PING-MIB.yamlファイルが./mibsディレクトリに保存されます。
$ ls -la ./mibs
合計 152
drwxrwxr-x 2 kooshin kooshin 4096 2月 7 18:54 .
drwxrwxr-x 4 kooshin kooshin 4096 2月 7 18:40 ..
-rw-r--r-- 1 kooshin kooshin 16208 2月 7 18:00 CISCO-PING-MIB
-rw-rw-r-- 1 kooshin kooshin 1247 2月 7 18:54 CISCO-PING-MIB.yaml
-rw-r--r-- 1 kooshin kooshin 16397 2月 7 18:00 CISCO-SMI
-rw-r--r-- 1 kooshin kooshin 102591 2月 7 18:00 CISCO-TC
$ cat mibs/CISCO-PING-MIB.yaml
---
ciscoPingMIB: 1.3.6.1.4.1.9.9.16
ciscoPingMIBObjects: 1.3.6.1.4.1.9.9.16.1
ciscoPingTable: 1.3.6.1.4.1.9.9.16.1.1
ciscoPingEntry: 1.3.6.1.4.1.9.9.16.1.1.1
ciscoPingSerialNumber: 1.3.6.1.4.1.9.9.16.1.1.1.1
ciscoPingProtocol: 1.3.6.1.4.1.9.9.16.1.1.1.2
ciscoPingAddress: 1.3.6.1.4.1.9.9.16.1.1.1.3
ciscoPingPacketCount: 1.3.6.1.4.1.9.9.16.1.1.1.4
ciscoPingPacketSize: 1.3.6.1.4.1.9.9.16.1.1.1.5
ciscoPingPacketTimeout: 1.3.6.1.4.1.9.9.16.1.1.1.6
ciscoPingDelay: 1.3.6.1.4.1.9.9.16.1.1.1.7
ciscoPingTrapOnCompletion: 1.3.6.1.4.1.9.9.16.1.1.1.8
ciscoPingSentPackets: 1.3.6.1.4.1.9.9.16.1.1.1.9
ciscoPingReceivedPackets: 1.3.6.1.4.1.9.9.16.1.1.1.10
ciscoPingMinRtt: 1.3.6.1.4.1.9.9.16.1.1.1.11
ciscoPingAvgRtt: 1.3.6.1.4.1.9.9.16.1.1.1.12
ciscoPingMaxRtt: 1.3.6.1.4.1.9.9.16.1.1.1.13
ciscoPingCompleted: 1.3.6.1.4.1.9.9.16.1.1.1.14
ciscoPingEntryOwner: 1.3.6.1.4.1.9.9.16.1.1.1.15
ciscoPingEntryStatus: 1.3.6.1.4.1.9.9.16.1.1.1.16
ciscoPingVrfName: 1.3.6.1.4.1.9.9.16.1.1.1.17
ciscoPingMIBTrapPrefix: 1.3.6.1.4.1.9.9.16.2
ciscoPingMIBTraps: 1.3.6.1.4.1.9.9.16.2.0
ciscoPingMIBConformance: 1.3.6.1.4.1.9.9.16.3
ciscoPingMIBCompliances: 1.3.6.1.4.1.9.9.16.3.1
ciscoPingMIBGroups: 1.3.6.1.4.1.9.9.16.3.2
ciscoPingCompletion: 1.3.6.1.4.1.9.9.16.2.0.1
YAMLファイルの中身は、単純なオブジェクト名とOIDのハッシュです。このため、手作業でオブジェクト名とOIDのペアを作成することも簡単にできそうです。
Ruby内でプライベートMIBの参照
SNMP::MIB.newでインスタンスを作成し、load_moduleメソッドで対象のMIBをロードします。ここでは、mibs変数に保存してます。
VarBindを作成する場合は、SNMP::VarBind.newの代わりにmibs.varbindメソッドを呼び出すことで、OIDではなく名前で指定できます。
mibs.oidで、名前からOIDに変換。mibs.nameで、OIDから名前に変換。
MIBのモジュール名は省略できるため、今回はモジュール名を省略しています。
正式「CISCO-PING-MIB::ciscoPingEntry」、省略形「ciscoPingEntry」
require 'snmp'
# プライベートMIBを保持するmibs変数
mibs = SNMP::MIB.new
mibs.load_module('CISCO-PING-MIB', './mibs')
SNMP::Manager.open(host: '172.16.1.132', community: 'private') do |manager|
# ciscoPingEntryStatusのVarBindを作成し、snmpsetする
varbind = mibs.varbind('ciscoPingEntryStatus.111', SNMP::Integer.new(5))
manager.set(varbind)
# ciscoPingEntryをsnmpwalkする
manager.walk(mibs.oid('ciscoPingEntry')) do |row|
puts "#{mibs.name(row.name)}\t#{row.value}"
end
end
実行結果
上記のスクリプトを実行すると、下記の結果になります。
$ ruby dev1.rb
CISCO-PING-MIB::ciscoPingPacketCount.111 5
CISCO-PING-MIB::ciscoPingPacketSize.111 100
CISCO-PING-MIB::ciscoPingPacketTimeout.111 2000
CISCO-PING-MIB::ciscoPingDelay.111 0
CISCO-PING-MIB::ciscoPingTrapOnCompletion.111 2
CISCO-PING-MIB::ciscoPingCompleted.111 2
CISCO-PING-MIB::ciscoPingEntryStatus.111 3
CISCO-PING-MIB::ciscoPingVrfName.111 default