rubyからipmi操作してみる(ruby-ipmitoolを利用)
環境構築
rubyにはruby-ipmitoolというgemパッケージがある。
これを使えばipmi操作ができそう。
ということで導入して触ってみる。
インストール方法はgem installで一発です。
# gem install ruby-ipmitool
irbで使えるかどうか確認してみます。
$ irb >require 'ruby-ipmitool' SyntaxError: /usr/local/ruby/1.9.2/lib/ruby/gems/1.9.1/gems/ruby-ipmitool-0.4/lib/ruby-ipmitool.rb:51: syntax error, unexpected keyword_do, expecting keyword_then or ';' or '\n' /usr/local/ruby/1.9.2/lib/ruby/gems/1.9.1/gems/ruby-ipmitool-0.4/lib/ruby-ipmitool.rb:194: syntax error, unexpected keyword_end, expecting $end from /usr/local/ruby/1.9.2/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:57:in `require' from /usr/local/ruby/1.9.2/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:57:in `rescue in require' from /usr/local/ruby/1.9.2/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:35:in `require' from (irb):2 from /usr/local/ruby/1.9.2/bin/irb:12:in `<main>'
するとこんな感じでエラーが・・・
どうやらruby-ipmitool.rbの51行目にsyntax errorがある模様。
ということでruby-ipmitool.rbを確認。
48 #Run a ping check to see if the host is responding 49 def check_host 50 result = `ping -q -c 2 #{@conn[:host]}` 51 if ($?.exitstatus == 0) do 52 pingable = true 53 else 54 pingable = false 55 end 56 pingable 57 end
51行目を見ると、if文の後ろにdoが書かれている。
このdoをthenに変更して、再度実行してみます。
$ irb >require 'ruby-ipmitool' =>true
すると通りました。
github上の最新のruby-ipmitool.rbを見てもこの記述方法なのでそのままだとうまくいかないのかも。
ruby 1.9.2で試したのがまずかったのかな。
接続方法
ipmitoolで接続する方法。
とりあえずirbで試してみます。
接続先のIPを10.1.1.1、IPMI接続ユーザ名をipmi_user,IPMI接続パスワードをipmipasswordとすると下記のようになります。
$ irb irb(main):001:0> require 'ruby-ipmitool' => true irb(main):002:0> conn = Ipmitool.new(:host => '10.1.1.1', :user => 'ipmi_user', :password => 'ipmipassword') => #<Ipmitool:0x00000008642fa0 @conn={:host=>"10.1.1.1", :user=>"ipmi_user", :password=>"ipmipassword", :check_host=>true, :binary=>"/usr/bin/ipmitool"}>
こうすることによってIPMI接続が可能になりました。
まず第1歩としてsensor listの出力結果を取得してみようと思います。
irb(main):003:0> conn.sensor Invalid sensor command: [] NoMethodError: undefined method `split' for nil:NilClass from /usr/local/ruby/1.9.2/lib/ruby/gems/1.9.1/gems/ruby-ipmitool-0.4/lib/ruby-ipmitool.rb:64:in `sensor' from (irb):6 from /usr/local/ruby/1.9.2/bin/irb:12:in `<main>'
するとエラーが・・・
ライブラリの中身を確認してみると、ipmitoolコマンド実行部分の実装が怪しい模様。
def run_command(command, *args) `#{@conn[:binary]} -H #{@conn[:host]} -U #{@conn[:user]} -P #{@conn[:password]} #{command} #{args unless args.nil?}`.downcase! end
ipmitoolコマンドを実行しているのは上記部分ですが、引数としてargsをとっています。
ここでsensorが実行された際、argsは空でやってくるので、ipmitoolコマンドの実際の実行内容は下記のようになっています。
ipmitool -H 10.1.1.1 -U ipmi_user -P ipmipassword sensor []
[]が余分です。
ということで、ここも書き換え。
def run_command(command, *args) `#{@conn[:binary]} -H #{@conn[:host]} -U #{@conn[:user]} -P #{@conn[:password]} #{command} #{args unless args.size == 0}`.downcase! end
これでargs配列のサイズが0の場合は何もipmitoolコマンドの引数として渡さないようにしました。
すると実行可能になりこんな結果が返ってきます。
irb(main):003:0> conn.sensor => { :bios=>["na ", "discrete ", "na ", "na ", "na ", "na ", "na ", "na ", "na"], :acpi_state=>["0x1 ", "discrete ", "0x0100| na ", "na ", "na ", "na ", "na ", "na"], :system_reset=>["0x0 ", "discrete ", "0x0000| na ", "na ", "na ", "na ", "na ", "na"], :cpu_fan=>["1980.590 ", "rpm ", "ok ", "na ", "na ", "na ", "na ", "771.962 ", "na"], :system_fan=>["1766.472 ", "rpm ", "ok ", "na ", "na ", "na ", "na ", "771.962 ", "na"], :system_12v=>["12.264 ", "volts ", "ok ", "na ", "11.368 ", "na ", "na ", "12.600 ", "na"], :system_5v=>["5.242 ", "volts ", "ok ", "na ", "4.820 ", "na ", "na ", "5.335 ", "na"], :system_aux_5v=>["5.101 ", "volts ", "ok ", "na ", "4.820 ", "na ", "na ", "5.335 ", "na"], :system_33v=>["3.326 ", "volts ", "ok ", "na ", "3.219 ", "na ", "na ", "3.557 ", "na"], :system_aux_33v=>["3.357 ", "volts ", "ok ", "na ", "3.219 ", "na ", "na ", "3.557 ", "na"], :cpu_vcore=>["1.117 ", "volts ", "ok ", "na ", "0.823 ", "na ", "na ", "1.568 ", "na"], :cpu_12v=>["12.264 ", "volts ", "ok ", "na ", "11.368 ", "na ", "na ", "12.600 ", "na"], :ht_12v=>["1.196 ", "volts ", "ok ", "na ", "1.117 ", "na ", "na ", "1.235 ", "na"], :memory_vcore=>["1.813 ", "volts ", "ok ", "na ", "1.666 ", "na ", "na ", "1.862 ", "na"], :memory_vterm=>["0.902 ", "volts ", "ok ", "na ", "0.804 ", "na ", "na ", "0.970 ", "na"], :mcp55_15v=>["1.499 ", "volts ", "ok ", "na ", "1.372 ", "na ", "na ", "1.568 ", "na"], :mcp55_14v=>["1.411 ", "volts ", "ok ", "na ", "1.235 ", "na ", "na ", "1.509 ", "na"], :pci_system_err=>["na ", "discrete ", "na ", "na ", "na ", "na ", "na ", "na ", "na"], :mem_recover_err=>["na ", "discrete ", "na ", "na ", "na ", "na ", "na ", "na ", "na"], :memunrecover_er=>["na ", "discrete ", "na ", "na ", "na ", "na ", "na ", "na ", "na"], :rcpu_diode_1=>["30.000 ", "degrees c ", "ok ", "na ", "na ", "na ", "na ", "85.000 ", "na"], :ambient=>["31.000 ", "degrees c ", "ok ", "na ", "na ", "na ", "na ", "53.000 ", "na"], :local_vrd0_temp=>["35.000 ", "degrees c ", "ok ", "na ", "na ", "na ", "na ", "85.000 ", "na"], :"therm-trip"=>["0x0 ", "discrete ", "0x0100| na ", "na ", "na ", "na ", "na ", "na"], :cpu_prochot=>["0x0 ", "discrete ", "0x0100| na ", "na ", "na ", "na ", "na ", "na"], :lom_link_status=>["0x1 ", "discrete ", "0x0200| na ", "na ", "na ", "na ", "na ", "na"], :lo100_present=>["0x0 ", "discrete ", "0x0100| na ", "na ", "na ", "na ", "na ", "na"], :watchdog=>["na ", "discrete ", "na ", "na ", "na ", "na ", "na ", "na ", "na"] }
これを実際のipmitoolコマンドの実行結果と比較すると
# ipmitool -H 10.1.1.1 -U ipmi_user -P ipmipassword sensor BIOS | na | discrete | na | na | na | na | na | na | na ACPI State | 0x1 | discrete | 0x0100| na | na | na | na | na | na System Reset | 0x0 | discrete | 0x0000| na | na | na | na | na | na CPU Fan | 1980.590 | RPM | ok | na | na | na | na | 771.962 | na System Fan | 1750.700 | RPM | ok | na | na | na | na | 771.962 | na System 12V | 12.264 | Volts | ok | na | 11.368 | na | na | 12.600 | na System 5V | 5.242 | Volts | ok | na | 4.820 | na | na | 5.335 | na System AUX 5V | 5.101 | Volts | ok | na | 4.820 | na | na | 5.335 | na System 3.3V | 3.326 | Volts | ok | na | 3.219 | na | na | 3.557 | na System AUX 3.3V | 3.357 | Volts | ok | na | 3.219 | na | na | 3.557 | na CPU Vcore | 1.117 | Volts | ok | na | 0.823 | na | na | 1.568 | na CPU 12V | 12.264 | Volts | ok | na | 11.368 | na | na | 12.600 | na HT 1.2V | 1.196 | Volts | ok | na | 1.117 | na | na | 1.235 | na Memory Vcore | 1.813 | Volts | ok | na | 1.666 | na | na | 1.862 | na Memory Vterm | 0.902 | Volts | ok | na | 0.804 | na | na | 0.970 | na MCP55 1.5V | 1.499 | Volts | ok | na | 1.372 | na | na | 1.568 | na MCP55 1.4V | 1.411 | Volts | ok | na | 1.235 | na | na | 1.509 | na PCI System Err | na | discrete | na | na | na | na | na | na | na Mem Recover Err | na | discrete | na | na | na | na | na | na | na MemUnrecover Er | na | discrete | na | na | na | na | na | na | na RCPU Diode 1 | 27.000 | degrees C | ok | na | na | na | na | 85.000 | na Ambient | 31.000 | degrees C | ok | na | na | na | na | 53.000 | na Local VRD0 Temp | 35.000 | degrees C | ok | na | na | na | na | 85.000 | na Therm-Trip | 0x0 | discrete | 0x0100| na | na | na | na | na | na CPU Prochot | 0x0 | discrete | 0x0100| na | na | na | na | na | na LOM Link Status | 0x1 | discrete | 0x0200| na | na | na | na | na | na LO100 Present | 0x0 | discrete | 0x0100| na | na | na | na | na | na Watchdog | na | discrete | na | na | na | na | na | na | na
同じ項目が取れてきているのがわかります。(※値が違うのは実行タイミングの違いによるものです)
sensorアイテムの値は全てdowncaseされ、空白は_に置き換えられています。
なので、上記のCPU Fanの値だけを見たければこのようにします。
irb(main):004:0> conn.sensor.cpu_fan => ["1980.590 ", "rpm ", "ok ", "na ", "na ", "na ", "na ", "771.962 ", "na"]
ちょっと試してみて、中身を見てみましたが、
ruby-ipmitoolは結局ipmitoolのコマンドのwrapperです。
サーバにipmitoolが導入されていないと動きません。