zbxapiを使ってZabbixにItemを追加する

2015.05.08

Ruby歴=入社歴+1ヶ月の横山です。

今回はZabbix API+Rubyを使って、
テンプレート(もしくはホスト)にたくさん登録したいアイテムがあるけど、
手作業では登録したくない場合のサンプルになればと思います。

準備

Amazon Linux 2015.03のt2.microを準備出来ればそれが一番早いと思いますが、
Rubyが動く環境であれば、大丈夫だと思います。

$ ruby --version
ruby 2.0.0p643 (2015-02-25) [x86_64-linux]

あと、Zabbixが自由に触れる環境があること。
この検証では、Zabbix 2.2を使用しています。

パッケージインストール

gemを使ってzbxapiサクッと入れる事が可能です。
但し、バージョンは、0.3.8を指定して入れて下さい
※理由は後述

$ gem install zbxapi -v 0.3.8
Fetching: zbxapi-0.3.8.gem (100%)
Successfully installed zbxapi-0.3.8
Parsing documentation for zbxapi-0.3.8
Installing ri documentation for zbxapi-0.3.8
Done installing documentation for zbxapi after 0 seconds
1 gem installed

コード

流れと致しまして、
1.ZabbixからAPIのauthトークンもらう
2.登録するためのテンプレートIDを template.get で取得する
3.item.create するためのparamを設定する。先ほど取得したテンプレートIDは hostid に設定する。
と、なります。

require 'zbxapi'

zabbix = ZabbixAPI.new('http://zabbix-host/zabbix')
zabbix.login('user', 'password')

template_id = zabbix.template.get(filter: {name: 'template demo'}).first['templateid']

item_params = {
  hostid: template_id,
  name: 'demo item',
  type: 3,
  value_type: 0,
  key_: "net.tcp.service[http,127.0.0.1,80]"
}

zabbix.item.create(item_params)

paramにある、 type valut_type はそれぞれ、GUIから登録際の タイプ データ型 に相当します。
ここでは、タイプを「シンプルチェック」、データ型を「数値(整数)」に設定しています
詳しくは、Zabbix ドキュメントをご参照下さい。

エラー対処

実は上記コード実行してもエラーが出て登録が失敗します。

$ ruby run.rb
/home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/zbxapi.rb:429:in `do_request': ZbxAPI_ExceptionLoginPermission
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/zbxapi.rb:342:in `api_call'
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/api_classes/api_dsl.rb:275:in `do'
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/api_classes/api_dsl.rb:404:in `block in add'
	from run.rb:17:in `<main>'

しかし、これだけではわからないのでzbxapiのdubugレベルを4に設定し再度確認してみます。

zabbix = ZabbixAPI.new('http://zabbix-host/zabbix')
↓
zabbix = ZabbixAPI.new('http://zabbix-host/zabbix', :debug => 4)
$ ruby run.rb
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"user.login","params":{"user":"Admin_API","password":"zabbix"},"auth":null,"id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"ad0686b2f29079fdd0d1d4676f08f5c0","id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"APIInfo.version","params":{},"auth":"ad0686b2f29079fdd0d1d4676f08f5c0","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"2.2.9","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"template.get","params":{"filter":{"name":"template demo"}},"auth":"ad0686b2f29079fdd0d1d4676f08f5c0","id":2}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":[{"templateid":"10153"}],"id":2}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"item.create","params":{"hostid":"10153","name":"demo item","type":3,"value_type":0,"key_":"net.tcp.service[http,127.0.0.1,80]"},"auth":"ad0686b2f29079fdd0d1d4676f08f5c0","id":4}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params.","data":"Item will not be refreshed. Please enter a correct update interval."},"id":4}
/home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/zbxapi.rb:429:in `do_request': ZbxAPI_ExceptionLoginPermission
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/zbxapi.rb:342:in `api_call'
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/api_classes/api_dsl.rb:275:in `do'
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.8/api_classes/api_dsl.rb:404:in `block in add'
	from run.rb:16:in `<main>'

注目すべきは、

D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params.","data":"Item will not be refreshed. Please enter a correct update interval."},"id":4}

ですね、先ほどのドキュメントを確認すると、更新時間の「delay(required)」のパラメータが足りませんでした。
パラメータに delay: 30 を追加し、再度実行してみます。

item_params = {
  hostid: template_id,
  name: 'demo item',
  type: 3,
  value_type: 0,
  key_: "net.tcp.service[http,127.0.0.1,80]",
  delay: 30
}
$ ruby run.rb
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"user.login","params":{"user":"Admin_API","password":"zabbix"},"auth":null,"id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"1e2a5931bd6d2f0f7ada48552ebeac6d","id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"APIInfo.version","params":{},"auth":"1e2a5931bd6d2f0f7ada48552ebeac6d","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"2.2.9","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"template.get","params":{"filter":{"name":"template demo"}},"auth":"1e2a5931bd6d2f0f7ada48552ebeac6d","id":2}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":[{"templateid":"10153"}],"id":2}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"item.create","params":{"hostid":"10153","name":"demo item","delay":30,"type":3,"value_type":0,"key_":"net.tcp.service[http,127.0.0.1,80]"},"auth":"1e2a5931bd6d2f0f7ada48552ebeac6d","id":4}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":{"itemids":["24633"]},"id":4}

item.create の実行に成功すると作成したitemidが取得できます。
また、今回は1個のparamを指定して作りましたが、リストにして複数のparamを指定し複数のアイテムを作成することが出来ます

item_params = [{
  hostid: template_id,
  name: 'demo item',
  delay: 30,
  type: 3,
  value_type: 0,
  key_: "net.tcp.service[http,127.1.0.1,80]"
},
{
  hostid: template_id,
  name: 'demo item',
  delay: 30,
  type: 3,
  value_type: 0,
  key_: "net.tcp.service[http,127.2.0.1,80]"
}]
$ ruby run.rb
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"user.login","params":{"user":"Admin_API","password":"zabbix"},"auth":null,"id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"5756a540acbac4ad903ae53cc2792e87","id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"APIInfo.version","params":{},"auth":"5756a540acbac4ad903ae53cc2792e87","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"2.2.9","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"template.get","params":{"filter":{"name":"template demo"}},"auth":"5756a540acbac4ad903ae53cc2792e87","id":2}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":[{"templateid":"10153"}],"id":2}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"item.create","params":[{"hostid":"10153","name":"demo item","delay":30,"type":3,"value_type":0,"key_":"net.tcp.service[http,127.1.0.1,80]"},{"hostid":"10153","name":"demo item","delay":30,"type":3,"value_type":0,"key_":"net.tcp.service[http,127.2.0.1,80]"}],"auth":"5756a540acbac4ad903ae53cc2792e87","id":3}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":{"itemids":["24636","24637"]},"id":3}

おまけ

検証用にもう一つコードを準備します。
Zabbix APIにログインするだけのコードです。

require 'zbxapi'

zabbix = ZabbixAPI.new('http://zabbix-host/zabbix', :debug => 4)
zabbix.login('user', 'password')

こちらの実行結果は以下の様になります。

$ ruby run2.rb
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"user.login","params":{"user":"Admin_API","password":"zabbix"},"auth":null,"id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"32e3f668646c404e10c20d29ec293146","id":0}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:408 Sending: {"jsonrpc":"2.0","method":"APIInfo.version","params":{},"auth":"32e3f668646c404e10c20d29ec293146","id":1}
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:410 Response Code: 200
D4 .../zbxapi-0.3.8/zbxapi.rb:do_request:411 Response Body: {"jsonrpc":"2.0","result":"2.2.9","id":1}

次に、zbxapiのバージョンを最新にして実行してみます

$ gem uninstall zbxapi
Successfully uninstalled zbxapi-0.3.8
$ gem install zbxapi
Fetching: zbxapi-0.3.10.gem (100%)
Successfully installed zbxapi-0.3.10
Parsing documentation for zbxapi-0.3.10
Installing ri documentation for zbxapi-0.3.10
Done installing documentation for zbxapi after 0 seconds
1 gem installed
$ ruby run2.rb
D4 .../zbxapi-0.3.10/zbxapi.rb:json_obj:203 Method:: user.login
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:415 Sending: {"jsonrpc":"2.0","method":"user.login","params":{"user":"Admin_API","password":"zabbix"},"id":0}
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:417 Response Code: 200
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:418 Response Body: {"jsonrpc":"2.0","result":"aed97b47480cd46f09558c0c0273c0f7","id":0}
D4 .../zbxapi-0.3.10/zbxapi.rb:json_obj:203 Method:: APIInfo.version
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:415 Sending: {"jsonrpc":"2.0","method":"APIInfo.version","params":{},"id":1}
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:417 Response Code: 200
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:418 Response Body: {"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params.","data":"Not authorized"},"id":1}
D4 .../zbxapi-0.3.10/zbxapi.rb:json_obj:203 Method:: user.authenticate
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:415 Sending: {"jsonrpc":"2.0","method":"user.authenticate","params":{"user":"Admin_API","password":"zabbix"},"auth":"aed97b47480cd46f09558c0c0273c0f7","id":2}
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:417 Response Code: 200
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:418 Response Body: {"jsonrpc":"2.0","result":"13ac5987c67c53618bc68c65233cf26b","id":2}
D4 .../zbxapi-0.3.10/zbxapi.rb:json_obj:203 Method:: APIInfo.version
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:415 Sending: {"jsonrpc":"2.0","method":"APIInfo.version","params":{},"id":3}
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:417 Response Code: 200
D4 .../zbxapi-0.3.10/zbxapi.rb:do_request:418 Response Body: {"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params.","data":"Not authorized"},"id":3}
/home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.10/zbxapi.rb:262:in `rescue in login': Invalid User or Password (ZbxAPI_ExceptionBadAuth)
	from /home/ec2-user/.gem/ruby/2.0/gems/zbxapi-0.3.10/zbxapi.rb:249:in `login'
	from run2.rb:4:in `<main>'

ログを見る限り、login関数実行時に APIInfo.version を見るときにauthトークンを付与していないので、失敗してるみたいです。
このバグにハマった場合は、バージョン指定してzbxapiを入れなおしましょう。

まとめ

結構簡単にスクリプトを組めるので、
アイテムを大量に手作業で入れなきゃならなくなった時の参考になればいいなと思います。