LoginSignup
10

More than 5 years have passed since last update.

Ruby SNMPでプライベートMIBを扱う

Posted at

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」

dev1.rb
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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10