2014年2月26日

KompiraからZabbixのグラフを取得してメール送信してみる

はじめに

先日のOSS運用管理勉強会で Kompira と Zabbix の連携ソリューションを紹介しました(発表資料はこちら)が、そのデモンストレーションの中で障害検出時に「Zabbix のグラフ画像を取得してメールで送信する」というのを行ないました。今回はその部分を簡単にしたものをご紹介したいと思います。

なお Kompira は ver 1.3.4、Zabbix は 2.2.1 を利用しています。

事前調査

Zabbixグラフ画像の取得方法

Zabbixのグラフ画像は例えば以下のような URL で取得できます。

http://example.com/zabbix/chart2.php?graphid=グラフID&period=3600&width=800

ただし、この際に Zabbix のセッションIDを cookie で渡す必要があります。セッションIDは Zabbix にログインしたときに割り当てられる値ですが、今回は Zabbix API を利用してログインしてセッションIDを取得するようにします。

また、URLパラメータの「グラフID」の部分は Zabbix で各グラフに割り当てられている ID を指定する必要があるので、事前に確認しておいてください(確認方法は後述)。

その他のURLパラメータは、以下のとおりです。
  • period : グラフ化する期間(秒数)
  • width : グラフ画像の横幅(ピクセル)
他にも指定できるパラメータがあるようなので、興味がある方は Zabbix の仕様を確認してみてください。

ZabbixグラフIDの確認方法


Zabbix のグラフ表示画面でグラフの上にあるタイトル部分下にある目盛り部分で右クリックして別ウィンドウ(または別タブ)で表示してみてください。先に書いたような URL で、以下のようにグラフ画像だけが表示されているかと思います。URL のパラメータ部分にある graphid= に続く数字が、そのグラフに割り当てられたグラフIDになります。


このグラフの場合 547 がグラフIDとなります。

Zabbix API によるログイン

グラフ画像の取得のためにはセッションIDが必要になりますので、Zabbix API を利用して Zabbix にログインすることでセッションIDを取得します。Zabbix 2.2 の場合は user.login という API を呼び出すことでログインできます。API の詳細については以下を確認してください。


この API を呼び出すには「ユーザ名」と「パスワード」が必要で、呼び出しに成功すると「セッションID」が結果として得られます。

実装

今回作成するオブジェクトは全て /samples/Zabbixグラフ送信 というディレクトリに配置することにします。

Zabbixサーバ情報

ログインに必要な情報である Zabbix サーバの URL、ユーザ名、パスワードを保持する環境変数オブジェクトを「Zabbixサーバ情報」という名前で作成します。また取得したセッションIDも保持できるようにしておきます。

それぞれ url, user, password, sessionid という名称で環境変数に記入しておきます。ただし sessionid はログイン時にジョブフローから書き込みますので、この段階では空欄にしておきます。

作成した「Zabbixサーバ情報」オブジェクトを以下に示します。


ZabbixAPI呼び出し

Zabbix へのログインを行なうために、Zabbix API を呼び出すジョブフローを「ZabbixAPI呼び出し」という名前で作成します。なお、このジョブフローはログイン以外の Zabbix API も呼び出せるように少し汎用的に作っておくことにします。


ポイントとなる箇所を簡単に説明します。

  • 8~14行目、Zabbix API の呼び出しに必要なパラメータを準備しています。パラメータの基本は API の種類を示す method と、API の種類毎に決められた形式の params、および認証のためにセッションIDを渡す auth です。API 呼び出し結果を区別するための id は、今回は利用しないため 1 固定とします。jsonrpc'2.0' と指定することが Zabbix API で決められているため固定とします。
  • 15行目、urlopen() 組み込みジョブを利用して Zabbix API を呼び出しています。上で準備したパラメータを JSON 形式で渡すために、引数 encode='json' を指定しています。
  • 23行目、Zabbix API を呼び出した結果が JSON 形式で帰って来ていますので、json_parse() 組み込み関数を利用してジョブフローで利用できる辞書形式に変換しています。
  • 24~33行目、呼び出した API が user.login の場合はセッションIDが result として得られるので、「Zabbixサーバ情報」環境変数の sessionid に書き込んでいます。user.logout を呼び出した場合は環境変数の sessionid をクリアしています。
  • 34行目、Zabbix API の呼び出し結果で得られた result 部分をジョブフローの戻り値として return しています。


Zabbixグラフ取得

得られたセッションIDを利用して Zabbix からグラフ画像を取得するジョブフローを「Zabbixグラフ取得」という名前で作成します。このジョブフローは「グラフID」を指定すると、それに対応するグラフ画像データを返すように作ります。



ポイントとなる箇所を簡単に説明します。

  • 1行目は、取得するグラフIDを指定するパラメータ graphid を定義しています
  • 2~3行目、グラフ化する期間やグラフ画像の幅もパラメータとしていますが、デフォルト値を定義しておくことでパラメータを省略してこのジョブフローを呼び出せるようにしておきます。
  • 10行目で、(次節のジョブフローで)取得済みのセッションIDを zbx_sessionid という名前の cookie で渡すための準備をしています。
  • 11~12行目、グラフIDおよびその他パラメータを含んだ URL を準備しています。
  • 13行目、urlopen() 組み込みジョブを利用して、グラフ画像の取得を行っています。辞書型データを cookies という引数で渡すことで、URL アクセス時の cookie を指定しています。
  • 20行目、正常にアクセスできた時は、レスポンス本文が画像データなのでジョブフローの戻り値として呼び出し元に返す。
  • 22,25行目、何らかのエラーが発生した場合は status=1 として異常ステータスを呼び出し元に返します。


Zabbixグラフ送信

上で準備したジョブフローを組合せて、Zabbix にログインおよび画像取得を行ってメールで送信するジョブフローを「Zabbixグラフ送信」という名前で作成します。このジョブフローでは取得するグラフを複数指定できること、および、メールの送信先や表題なども指定できるように作ります。


ポイントとなる箇所を簡単に説明します。
  • 1行目は、グラフIDを指定するパラメータ graphids を定義しています。複数のグラフを指定できるように配列形式で渡されることを期待しています。
  • 2~5行目、メール宛先などのメール送信に関連するパラメータを定義しています。いくつかのパラメータは簡単のためにデフォルト値を指定しています。
  • 11行目で、「ZabbixAPI呼び出し」ジョブフローで user.login を呼び出して、セッションIDを取得しています。パラメータのユーザ名とパスワードには環境変数に設定したものが渡され、結果得られたセッションIDは環境変数に記録されます。
  • 18行目、得られた複数の画像データを格納する空の配列変数 files を用意しておきます。
  • 19~25行目、グラフID毎に「Zabbixグラフ取得」ジョブフローを呼び出して、グラフ画像のデータを取得しています。取得できた場合は namedata という要素を持つ辞書形式(これがひとつのファイルに相当する)にして、それを配列 files に追加していきます。ファイル名(name)は Zabbix から得られないので、グラフID + ".png" としています。
  • 33行目、グラフ画像が1枚以上得られたときは、それらを添付ファイルとしたメールを to 宛に送信しています。mailto() 組み込みジョブの attach_files 引数には添付ファイルフィールドや、name, data 要素を持つ辞書を指定できます。またそれらを配列に入れて渡すことで複数のファイルを添付することができますので、その仕組みを利用しています。
  • 37行目、グラフ画像が得られなかったときは、メールを送信しません。
  • 43行目、Zabbix からログアウトするために、user.logout を呼び出しています。

実装オブジェクト一覧

以上で実装が完了しました。実装したオブジェクトの一覧は以下のようになっています。



動作確認

では実際にジョブフローを動かしてみましょう。

Zabbixグラフ送信の実行

ここでは3つのグラフ画像(グラフIDは 524, 525, 547)を取得して、自分宛てにメールを送信させたいと思います。「Zabbixグラフ送信」画面で、パラメータ欄 graphidsto を以下のように記入して「▶実行」ボタンを押して、ジョブフローを実行します。



パラメータ記入のポイント:

  • graphids は配列形式にするため [] で囲って複数のグラフIDを記入します。
  • to は文字列で指定するため ' または " で囲って記入します。


ジョブフロー実行結果

実行したジョブフローが問題なく完了すると、プロセス詳細画面のコンソールが以下のように表示されているはずです。


Zabbix にログインして、3枚のグラフ画像を取得してメールを送信し、最後にログアウトしている様子が分かります。

ちなみに手元の環境(Kompira と Zabbix を同時に動かしています)でこのジョブフローの実行時間は約9秒でした。

受信メール確認

最後に、今回作成したジョブフローが Zabbix からグラフを取得してメールを送信できているか確認してみると、ちゃんと以下のようなメールが届いていました。



スクリーンショットには入りきりませんでしたが、3枚目のグラフ画像も添付されています。

まとめ

今回は Kompira で Zabbix からグラフ画像を取得するために、urlopen() 組み込みジョブを利用してみました。また mailto() 組み込みジョブに取得した画像データを渡すことで、添付ファイルとしてメールを送ることができることを示しました。

また、セッション ID を取得するために、Zabbix API を呼び出すジョブフローも実装してみました。お気付きの通り、ログインやログアウト以外の API にも利用できますので、これをベースにして Kompira と Zabbix の様々な連携の可能性も広がるかと思います。

より実践に近いデモンストレーションでは、Zabbix が障害を検出した時に Kompira からサーバに自動的にログインしてプロセス状態やログを収集したうえで、HTML メールにそれらの情報と共に(今回紹介した仕組みで取得した)グラフ画像をインラインに貼り付けて送信し、さらにクラウド電話サービスで障害発生の通知まで行っています。