PerlのZabbix API クライアントモジュールでZabbixを色々自動化

PerlでZabbix API クライアントモジュールを実装してみた。

ZabbixのAPIを利用して便利な状況は以下のような場合だろうか。

  • 自動インストールして立ち上がってきたサーバをAPI経由で自動で監視登録する
  • サービスインするサーバは開始処理と共に自動で監視を開始する
  • いらなくなったサーバは停止処理と共に自動で監視を停止する
  • 監視ホスト情報をAPI経由で定期的に取得して棚卸する
  • Zabbix APIのJSONでできることは全部できる(多分)

等だろうか。あくまで運用目線での利用用途を考えてみた。

実装自体はだいぶ前だが、結構使えるので、Zabbixを提供してもらっている感謝の意を込めて、こういう便利だと思ったものは公開していきたいと思う。現状、情報として出ているPerlでかかれたZabbixのAPIクライアントをサラっと調べてみたけど、本記事のモジュールの方が比較的シンプルかつ汎用性が高く、扱いやすいように思ったので公開に至った。

今回のZabbixモジュールは独自の実装補助モジュールを継承しているのだが、その説明は今回は置いておいて(重要なんですが)、Zabbixモジュールの使い方を中心に説明したいと思う。構成としては、System::BaseというモジュールをZabbix::APIモジュールが継承している。そのため、Zabbix::APIモジュールを使うにはSystem::Baseモジュールが必要になる。なので、最初に適当な場所にこれらのモジュールをダウンロードしておいておく。自分の場合はこのようにしてみた。本記事の目的としては、ZabbixモジュールでZabbix API クライアントをPerlで簡単に実装すること。

ソースはこちら。(SystemモジュールとZabbixモジュールを両方ダウンロードする必要がある)

$ ls /usr/local/lib/myperl_lib/
System/ Zabbix/

さっそく導入

まずはSystemモジュールやそれを継承したZabbixモジュールを使うための準備をする。

yumのレポジトリにrpmforgeを追加しておく

これ、意外とやってない人が多いように思うがかなり便利なので今回とは関係なく常にやった方がいいかもしれない。他のレポジトリとしてはepelとか色々ある。

  • rpmforgeを追加に必要なRPMをダウンロード(バージョンとかは適当に読み替え)
wget http://dag.wieers.com/rpm/packages/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
  • ダウンロードしたRPMをインストール
rpm –ivh rpmforge-release-0.3.6-1.el5.rf.i386.rpm
  • rpmforgeが有効になるように変更
vi /etc/yum.repos.d/rpmforge.repo
    • (変更前)
enabled = 1
    • (変更後)
enabled = 0

必要なPerlモジュールを導入

前述の通り、Zabbixモジュールが、Systemモジュールを継承しており、SystemモジュールにはいくつかのPerlモジュールを使っているので、動作に必要なモジュール群を導入する。

  • perl-Class-Accessorの導入
yum --enablerepo=rpmforge install perl-Class-Accessor
  • perl-Jcodeの導入
yum --enablerepo=rpmforge install perl-Jcode
  • perl-DBIの導入
yum install perl-DBI
  • perl-JSONの導入
yum --enablerepo=rpmforge install perl-JSON
  • perl-Data-Dumpの導入
yum --enablerepo=rpmforge install perl-Data-Dump
  • perl-LWP-UserAgent-Determinedの導入
yum --enablerepo=rpmforge install perl-LWP-UserAgent-Determined

これで準備は完了だ。

Zabbix::API::Clientの使い方

では、Zabbix API クライアントをどのように実現するかをサンプルスクリプトを例に解説したい。サンプルスクリプトはこちら

まずは、モジュールを読み込んでおく。

use lib "/usr/local/lib/myperl_lib";
use Zabbix::API::Client;

次にインスタンスを生成する時は、以下のようなメンバを与える。

my $API = Zabbix::API::Client->new(

    url             =>  "http://example.com/zabbix/api_jsonrpc.php",
    user_agent      =>  "Zabbix-API-Client",
    user            =>  "api-admin",
    pass            =>  "hogefuga",
    debug           =>  0,
    info            =>  0,
    warn            =>  0,
    error           =>  1,
    irc_owner       =>  $SCRIPT,
    tool_name       =>  $SCRIPT,
    log_file        =>  "/tmp/$SCRIPT.log",
    pid_file        =>  "/tmp/$SCRIPT.pid",
    lock_file       =>  "/tmp/$SCRIPT.lock",
    syslog_type     =>  $SCRIPT,

);

見ての通り、urlにAPIのURL、user_agentは好きな文字列、userはZabbix上で定義したAPI用のユーザー名、passはそのAPIユーザーのパスワード、他のメンバはSystemモジュールから継承したメンバになるので今回は説明は省略する。デバッグ出力やエラー出力を、任意のファイルやsyslogに吐く機能や、IRCに出力するときのニックネームやIRCサーバホストを指定したり、スクリプト実行時のPIDファイルの作成やLock機構の提供、そういった機能がSystemモジュールには含まれている。

話は戻って、これでインスタンスができたので、実際に以下のようなJSONのサンプルデータをAPIに食わしてみる。

{
    "object":"host",
    "method":"create",
    "params":{
        "host":"__HOST_NAME__",
        "ip":"__HOST_IPADDRESS__",
        "port":10050,
        "useip":1,
        "proxy_hostid":10047,
        "groups":[
                        {"groupid":__GROUP_ID1_},
                        {"groupid":__GROUP_ID2_}
                  ],
        "status":1,
        "templates":[
                            {"templateid":__TEMPLATE_ID1_},
                            {"templateid":__TEMPLATE_ID2_}
                    ],
        "macros":[
                        {"macro":"{$HOST_URL}", "value":"__HOST_IPADDRESS__"}
                  ],
        "profile":{
                        "devicetype":"AAA デバイス",
                        "tag":"なんちゃらサービス",
                        "hardware":"なんちゃらハード",
                        "location":"なんちゃらデータセンターの何チャララック"
                  }
    }
}

これは、Zabbix上にAPI経由で監視ホストを追加するためのサンプルJSONデータファイルだ。groupやtemplateidを指定しておくことで、ホストに監視項目を紐付けられる。このJSONは即座に監視をはじめるパラメータを入れていないので、登録した段階では監視無効になっている。しかるべきタイミングで監視を有効にしてやれば良い。ちなみ、即時監視をはじめるJSONの記述は以下のように記述してやれば良い。

        "status":0,

では食わせ方だが、ファイルから食わす場合は以下のように記述する。

$json_data = $API->json_from_file($json_file);

これによって、ファイルのJSONデータをPerlで扱うための連想配列に変換してくれる。そして、変換したjson_dataを以下のようにAPIに渡す。

my $response = $API->api_operation(
                                    $json_data->{method},
                                    $json_data->{object},
                                    $json_data->{params}
                                  );

結果は連想配列でリターンされてくるので、それをdump()で見てやれば良い。

print dump($response) . "\n";

また、ファイルだけでなくPerlの連想配列をJSONとして扱うこともできる。例えば、上述した監視を無効から有効にする場合は、以下のような連想配列をAPIに渡せば良い。まずは、有効にしたいホスト情報を以下のようなJSONをAPIに渡して取得する。

my $json_data_get = {

    method  =>  "get",
    object  =>  "host",
    params  =>  {
                    extendoutput    =>  1,
                    filter          =>  {
                                            host    =>  $HOST,
                                        }
                },
};

my $response = $API->api_operation(
    $json_data_get->{method},
    $json_data_get->{object},
    $json_data_get->{params}
);

そして、そこから得られたresponseデータの中から、ホスト名に紐付けられた一意のhostidを得て、そのhostidに対して監視を有効にするJSONを渡す。連想配列でのJSONデータは以下の通り。

my $start_host_json_data = {

    method  =>  "update",
    object  =>  "host",
    params  =>  {
                    hostid  =>  $response->{result}->[0]->{hostid},
                    status  =>  0,
                },

};

以上が、ZabbixAPIクライアントのモジュールの説明だ。非常に簡単に使えるのではないだろうか。今こういうのは結構あるのかもしれないが、当時(2年前)はあまりなくてZabbix APIの執筆中だらけのAPIの英語マニュアルを苦労して読みながら、独自で作ってみたら結構使えるモジュールになった。動かない等の指摘があれば、随時指摘してくださるとうれしいです。