Ruby zabbixapiでZabbixのAPIを利用してみる

 

マイブームと言ってもいいほど最近APIの話が続いちゃっています。
前回はRedmineで、今回はZabbixです。
Redmineに比べると情報量がとても少ないんですよね。どうしましょう。日本語のサイトが少ないようで、わざわざ日本語をキーワードに混ぜて日本語のウェブサイトを探すよりも、コマンドがメインなので海外のサイトでも気にせずじっくり見ていく方が効率が良いようです。いろいろと弄くりまわしてみて、やっとその答えが出てきました。
APIを使う事でどんなメリットがあるのかというと、あの重たいUIを使わなくてもいい!ということかな。
自分でZabbixのUI作ったった!なんていうほどの猛者はまだ見つかっていません!w

 

Zabbix.orgによると、利用できるモジュールは4つあります。

Docs/api/libraries – Zabbix.org: から

Ruby

  • Zabbix API by nelsonab (latest code seems to be on github) – a Ruby wrapper
  • Rubix by Dhruv Bansal – a Ruby library for working with the API and both retrieving and sending data to Zabbix server
  • zabbixapi by Express 42 – a Ruby gem, see README on github
  • zabby by Farzad Farid – a Ruby library and client for Zabbix

ではこの中から、zabbixapiを使ってみようと思います。

参考サイト

4種類それぞれのモジュールを検証している方がいらっしゃるので参考にしました。

Zabbix APIをRubyから利用する場合どのライブラリが良いのか調べてみる:

 

ではでは、進めていきますか。
そのままGemでインストールすると2.4.2が入るようです。

[takeken@centos]$ gem install zabbixapi

そのまま進めていくと、なんとまぁバージョンが合わないらしく、Zabbixのバージョンによって使えるバージョンが細かく分かれているようで、バージョンの不一致でやむなく入れ替えをすることにしました。

Zabbix API version: 2.0.9 is not support by this version of zabbixapi (RuntimeError)

念のためZabbixserverでもバージョンを確認しています。
だいぶ昔にインストールしているのでv2.0.9でした。

takeken@vincentina]# zabbix_server -V
Zabbix server v2.0.9

gemの入れなおしをします。Gemのコマンドもいろいろと覚えていないのでググって調べます。これは削除の短縮形です。基本的なものは覚えないとだね。

[takeken@centos]$ gem uni zabbixapi -v 2.4.2

今のZabbixのバージョンで使えるzabbixapiのバージョンを調べてみましょう。

zabbixapi | RubyGems.org | your community gem host:

File: README — Documentation for zabbixapi (2.4.2):

どうやら2.0.0になるらしいです。
Zabbixが2.2.9の場合は、zabbixapiのバージョンは2.2.0〜みたいです。

利用できるコマンドなどなど、色々な情報はGithubのサイトで確認。

express42/zabbixapi at zabbix2.0:

ずらずらとひと通りのコマンドがサンプルとして載せてあるようですね。
とりあえず今やりたいことは情報を取ることなのですがGetのコマンドが見当たらない。なぜ?
見方になかなか慣れなくてすぐに見つけれませんでしたが、hosts.getメソッドで取れるらしい事が分かりました。
まずはベースとなるスクリプトを作っていきたいと思います。

以下はサンプルソース。

require "zabbixapi"

Zabbix_url = "http://ホスト名/zabbix/api_jsonrpc.php"
Zabbix_id = 'Admin'
Zabbix_pass = 'パスワード'

=begin
通常の認証なら下記の記述
zbx = ZabbixApi.connect(
  :url => 'http://localhost/zabbix/api_jsonrpc.php',
  :user => 'Admin',
  :password => 'zabbix'
)
ベーシック認証の場合は下記の記述
zbx = ZabbixApi.connect(
  :url => 'http://localhost/zabbix/api_jsonrpc.php',
  :user => 'Admin',
  :password => 'zabbix',
  :http_password => 'foo',
  :http_user => 'bar'
)
=end

zbx = ZabbixApi.connect(
        :url => Zabbix_url , :user => Zabbix_id , :password => Zabbix_pass
)

puts "START"
# たとえば全ホスト
# p zbx.hosts.get(:output => "hosts")
# たとえば全アイテム
# p zbx.items.get(:output => "items")
puts
puts "vincentina"
puts zbx.hosts.get(:host => "vincentina")
puts
puts "zabbix server"
puts zbx.hosts.get(:host => "Zabbix Server")
puts "END"

上のスクリプトを実行すると指定しているホストが表示されます。
実は本番サーバーで検証しているので、今はGETだけの検証です。
監 視している対象のサーバーはこのVPS1台のみですが、昔の名残というか初期設定のZabbixServerが設定したままでしたので、せっかくなので2 台の名前でそれぞれ指定してみて、情報を取得できることを確認してみました。アイテムとかもそれぞれの指定した項目で取得できるはずだ。と思って試してみるとitems.getメソッドが使えました。

それぞれホストを指定した場合の結果は以下のように出ます。見やすいように途中で改行しています。

START

vincentina
{"maintenances"=>[], "hostid"=>"10085", "proxy_hostid"=>"0",
"host"=>"vincentina", "status"=>"0", "disable_until"=>"0",
"error"=>"", "available"=>"1", "errors_from"=>"0", "lastaccess"=>"0",
"ipmi_authtype"=>"-1", "ipmi_privilege"=>"2", "ipmi_username"=>"",
"ipmi_password"=>"", "ipmi_disable_until"=>"0", "ipmi_available"=>"0",
"snmp_disable_until"=>"0", "snmp_available"=>"0", "maintenanceid"=>"0",
"maintenance_status"=>"0", "maintenance_type"=>"0", "maintenance_from"=>"0",
"ipmi_errors_from"=>"0", "snmp_errors_from"=>"0", "ipmi_error"=>"",
"snmp_error"=>"", "jmx_disable_until"=>"0", "jmx_available"=>"0",
"jmx_errors_from"=>"0", "jmx_error"=>"", "name"=>"vincentina"}

zabbix server
{"maintenances"=>[], "hostid"=>"10084", "proxy_hostid"=>"0",
"host"=>"Zabbix server", "status"=>"1", "disable_until"=>"0",
error"=>"", "available"=>"1", "errors_from"=>"0", "lastaccess"=>"0",
"ipmi_authtype"=>"-1", "ipmi_privilege"=>"2", "ipmi_username"=>"",
"ipmi_password"=>"", "ipmi_disable_until"=>"0", "ipmi_available"=>"0",
"snmp_disable_until"=>"0", "snmp_available"=>"0", "maintenanceid"=>"0",
"maintenance_status"=>"0", "maintenance_type"=>"0", "maintenance_from"=>"0",
"ipmi_errors_from"=>"0", "snmp_errors_from"=>"0", "ipmi_error"=>"",
"snmp_error"=>"", "jmx_disable_until"=>"0", "jmx_available"=>"0",
"jmx_errors_from"=>"0", "jmx_error"=>"", "name"=>"Zabbix server"}
END

マニュアルなしだと大部分の意味が分からないですね。
itemに関しては、とにかく情報量がえげつない事もありまったく訳が分かりません。
ここでまず一つ勘違いがあって、Zabbixを使った事がないと意味が分からないかもしれませんが、itemsはitems、templateはtemplateであってリソースの情報ではないということです。
そもそもAPIというのはそういうものでしたね。
リソースの監視がしたい場合は、APIでグラフの操作できるので、グラフのAPIを使うことになりますかね。それは置いておいて、とにかくウェブ上にあまり情報がないので一般的な言い方をすると自分の足で探すということになります。ここではインターネット上なので手を使って探さなくてはなりません。

順番に色々とさわってみます。
zbx.graphs.get_ids_by_host(:host => hostname)

うーん。何だこの番号は。何だか良く分かりませんw

START
["560", "536", "537", "542", "588", "589", "590", "591", "592", "593", "594", "596", "597", "595", "538", "529", "530", "531", "532", "553", "554", "548", "549", "550", "543", "544", "555", "556", "557", "558"]
END

ものによってはfilterでフィルタリングできるみたいなので、これで試してみると・・・
zbx.graphs.get_ids_by_host(:host => hostname, filter => CPU)

CPUでフィルターされて一部だけの表示となりました。が、やっぱりよく分からない…

START
["529", "530", "531"]
END

 

灯台下暗しでゆっくり調べてみるとちゃんとClassとMethodsのマニュアルが置いてありました。当然ながら英語になっちゃいます。よくあることですね。

File: README — Documentation for zabbixapi (2.0.0):

Redmineに比べてGETだけではいまいち使いどころのビジョンが浮かばないので、作業効率がだんだんと落ちてきました。ぼちぼちPOST、UPDATE、DELETEの検証に進みたいと思います。
と、その前に検証作業用のZabbixを用意したいです。本番サーバーで検証をするのは愚の骨頂ですから。でもでもOSのインストールからやるのはめんどくさい!!

そんなときはVagrant〜!とZabbixを入れるChefのレシピは作ってなかった!ので、シェルスクリプト〜で代用しますw
あ〜〜〜んなにたくさんChefの回があったのに作っていなかったとは!!絶望しかけた!

・・・気をとりなおして検証用Zabbixを用意します。
念のためヒストリーを残してきます。

専用のディレクトリを作っておいて
cd vagrant/zabbix

ボックス名を確認。便利だね。
$ vagrant box list
centos5 (virtualbox, 0)
centos6 (virtualbox, 0)

vagrant init でVagrantfileを作成します。
$ vagrant init centos6

ブリッジ接続したいのでVarantfileを編集、パブリックを有効にします。
Vagrantfile
config.vm.network "public_network"

起動。
vagrant up

OSインストール後のセットアップとZabbixインストールまでやってくれるスクリプトを実行。
sh setup.sh

これで完成。

リブートしてみると、Zabbix-serverが動いていませんでしたorz
スクリプトの管理なんてしていないので仕方ないです。Zabbixの吐いているエラー内容とセットアップのスクリプトをチェックしていると、どうやら指定されていたバージョンが違っていたようです。
この辺はChefとかVagrantなら自動でやってくれるのでその辺が違うとこですかね。。
今回は手動で合わせます。親になって親のありがたみがわかると言うように、色々とやってみてこそものの違いがわかってくるのね。

mysql -uroot zabbix < /usr/share/doc/zabbix-server-mysql-2.2.8/create/schema.sql
mysql -uroot zabbix < /usr/share/doc/zabbix-server-mysql-2.2.8/create/images.sql
mysql -uroot zabbix < /usr/share/doc/zabbix-server-mysql-2.2.8/create/data.sql

上のコマンドを手動で実行してデータベースを作って終了です。スクリプトの方はzabbix-server-mysql-2.2.6になっていたので、その部分を修正しただけでOKでした。良かった。
トータルではほんの数分で検証用のZabbixの環境が出来上がりました。

[root@localhost ~]# service zabbix-server status
zabbix_server (pid  1996) is running...

それでは本題に戻り、POSTだとかUPDATEだとか、本体を操作する側のAPIを使ってZabbixのデータを動かしてみるとしますか。サンプルコードのままですが、ホストを追加してみます。

zbx.hosts.create_or_update(
  :host => "hogehoge",
  :interfaces => [
    {
      :type => 1,
      :main => 1,
      :ip => '10.0.0.1',
      :dns => 'server.example.org',
      :port => 10050,
      :useip => 0
    }
  ],
  :groups => [ :groupid => zbx.hostgroups.get_id(:name => "hostgroup") ]
)

成功しました!hogehogeが追加されました。

za01

イテレータを使ってhoge1からhoge10までのホストを一気に追加してみます。

ソース

range = 1..10
range.each do |x|
zbx.hosts.create_or_update(
  :host => "hoge#{x}",
  :interfaces => [
    {
      :type => 1,
      :main => 1,
      :ip => "10.0.0.#{x}",
      :dns => 'server.example.org',
      :port => 10050,
      :useip => 0
    }
  ],
  :groups => [ :groupid => zbx.hostgroups.get_id(:name => "hostgroup") ]
)

成功しました。

hoge01

 

続いては、UPdate Hostのテスト。
ステータスが0でホストが有効、1でホストが無効になるようです。

zzbx.hosts.update(
  :hostid => zbx.hosts.get_id(:host => "hogehoge"),
  :status => 0
)
#You can check host:
puts zbx.hosts.get_full_data(:host => "hogehoge")

この場合はhogehogeだけです。さきほど作ったhoge1からhoge10を一気に無効にしてみましょう。

イテレータで数字を回すだけなので簡単ですね。

range.each do |x|
zbx.hosts.update(
  :hostid => zbx.hosts.get_id(:host => "hoge#{x}"),
  :status => 1
)
#You can check host:
puts zbx.hosts.get_full_data(:host => "hoge#{x}")
end

こうなります。って画像だと結果しか分からないw
一応成功しています。

hoge02

 

続いては、Update Itemです。引数をitemにすると全アイテムを出力するので、さきほどの容量でステータス0とすると、全アイテム有効ということでしょうか。それは恐ろしいですね。
検証環境なのでやってみましょう。

うーん。これは上手く動かないみたいです。置いておきます。

 

色々と試してみたところ、コマンドをパズルのように当てはめて使うように思います。
ネストしていくという言い方をスルのでしょうか。
ホストやテンプレートに合わせてアクションやトリガーと絡めて、情報を取得するというのはなかなかむずかしそうです。
どこかのウェブサイトに監視も可能という事は記載されていたのでやりようによっては可能なのでしょう。

ある程度の事はできたのでこれでいったん終了!

 

Similar Posts:


Leave a Reply

Your email address will not be published. Required fields are marked *