Zabbix APIで複数ホストが1枚にいるグラフを簡単作成

# Zabbix APIで簡単グラフ作成

複数ホストで同じ項目を見たい、 ロードバランスしているサーバたちで積み上げグラフを見たいって時、 ありますよね。
Zabbix GUI上でそういったグラフを作る時は、 ホストや見たいグラフが多いとマウスクリックが多くてうんざりしてきます。 [^1]
そんな時にZabbix APIを使ってグラフを簡単に作成してみましょう。

## 環境
* Zabbix 3.0.7
* 作業はlocalhost上で行う

## 前提
* ホストが登録されている
* ホストに対して見たいアイテムが設定されている

## 手順

### 0. API で auth token を取得する
Zabbix APIを使うためには各リクエストに auth token (セッションIDかな?) を含む必要があります。
こちらに関しては[他に色々](https://www.google.co.jp/search?q=zabbix+api+auth+site%3Aqiita.com&oq=zabbix+api+auth+site%3Aqiita.com&gs_l=psy-ab.3...1074.3987.0.4182.15.12.0.0.0.0.268.1064.0j2j3.5.0....0...1.1.64.psy-ab..10.0.0....0.4yPWM2X0sv0)と記載がありますので割愛しますが、 以下のリクエストを送ってください。

```
curl -XPOST http://localhost/zabbix/api_jsonrpc.php \
-H "Content-Type: application/json-rpc" \
-d '{"jsonrpc": "2.0", "method": "user.login", "params": {"user": "ユーザ名","password": "パスワード"},"id": 1}'
```

成功すると、 32文字の token が返ってきます。 (以降の説明ではそれを `TOKEN` と記載します)
なお、 グラフを作成する権限のあるユーザを使ってください。

### 1. API で hostid を取得する
以下のリクエストで取得できます。 一行で返ってくるので、 less にパイプする等気をつけてください。

```
curl -XPOST http://localhost/zabbix/api_jsonrpc.php \
-H "Content-Type: application/json-rpc" \
-d '{"jsonrpc":"2.0", "method":"host.get", "id":1, "auth":"TOKEN", "params": {}}'
```

最終的に参照用で使いたいので、 [jq](https://www.google.co.jp/search?q=jq+site%3Aqiita.com&oq=jq+site%3Aqiita.com&gs_l=psy-ab.3...3390.5418.0.5510.15.15.0.0.0.0.187.1571.6j7.13.0....0...1.1.64.psy-ab..2.5.758...0j35i39k1j0i131k1j0i4k1j0i4i10k1j0i30k1j0i4i30k1j0i4i10i30k1.0.ztWtdNLZWXg) コマンドで必要な分だけcsvにしてしまいましょう。

```
(curlコマンド) | jq -r '.result[] | [.hostid, .host] | @csv' > hostid_host.csv
```

中身のcsvは以下のようになっています (見出し行はありません)

| hostid | host  |
|:------:|:-----:|
| 10001  | host1 |
| 10002  | host2 |
| 10003  | host3 |

### 2. API で itemid を取得する
同上です。 `method` が異なります。

```
curl -XPOST http://localhost/zabbix/api_jsonrpc.php \
-H "Content-Type: application/json-rpc" \
-d '{"jsonrpc":"2.0", "method":"item.get", "id":1, "auth":"TOKEN", "params": {}}'
```

csvデータも必要な分だけまた取り出しましょう。

```
(curlコマンド) | jq -r '.result[] | [.itemid, ._key, .name, .hostid] | @csv' > itemid__key_name_hostid.csv
```

| itemid | key                           | name             | hostid |
|:------:|:-----------------------------:|:----------------:|:-----:|
| 20001  | system.cpu.load[,avg1]        | CPUロードアベレージ   | 10001 |
| 20002  | system.cpu.load[,avg1]        | CPUロードアベレージ   | 10002 |
| 20003  | system.cpu.load[,avg1]        | CPUロードアベレージ   | 10003 |
| 20004  | system.cpu.util[,iowait,avg1] | CPU使用率(iowait) | 10001 |
| 20005  | system.cpu.util[,iowait,avg1] | CPU使用率(iowait) | 10002 |
| 20006  | system.cpu.util[,iowait,avg1] | CPU使用率(iowait) | 10003 |

### 3. 1と2の結果から必要な itemid を確認する

1と2で取得した結果をExcelなりRDBに入れて、 必要なデータを視認しやすいようにしておきましょう。 以下ではExcelでVLOOKUPした想定です。

| itemid | key                           | name             | hostid | host |
|:------:|:-----------------------------:|:----------------:|:-----:|:-----:|
| 20001  | system.cpu.load[,avg1]        | CPUロードアベレージ   | 10001 | host1 |
| 20002  | system.cpu.load[,avg1]        | CPUロードアベレージ   | 10002 | host2 |
| 20003  | system.cpu.load[,avg1]        | CPUロードアベレージ   | 10003 | host3 |
| 20004  | system.cpu.util[,iowait,avg1] | CPU使用率(iowait) | 10001 | host1 |
| 20005  | system.cpu.util[,iowait,avg1] | CPU使用率(iowait) | 10002 | host2 |
| 20006  | system.cpu.util[,iowait,avg1] | CPU使用率(iowait) | 10003 | host3 |

以降は、 "host1~3のCPUロードアベレージをまとめて1グラフに表示したい" という想定にします。
そうなると一緒に表示したいのは itemid の 20001, 20002, 20003ですね。

### 4. API で グラフを作成する

グラフを積み上げにするかどうか、 幅や高さをどうするか等オプションはありますが、 最低限必要なデータでAPIリクエストをし、 グラフを作って見ます。

前半は、一緒です。

```
curl -XPOST http://localhost/zabbix/api_jsonrpc.php \
-H "Content-Type: application/json-rpc" \
-d '{~~後述~~}'
```

後述となっている部分はこちらです。

```json
{
    "jsonrpc": "2.0",
    "method": "graph.create",
    "params": {
        "name": "APIテストグラフ",
        "gitems": [
            {
                "itemid": "20001",
                "color": "FF0000"
            },
            {
                "itemid": "20002",
                "color": "00FF00"
            },
            {
                "itemid": "20003",
                "color": "0000FF"
            }
        ]
    },
    "auth": "TOKEN",
    "id": 1
}
```

リクエストを送ると、 作成された graphid がレスポンスとして返ってきて、 GUI上で見ると以下のグラフが出来上がっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/90487/4943e937-caf2-82ad-dafd-754b34422430.png)

その他グラフに対するオプションは [Documentation の
 graph.create](https://www.zabbix.com/documentation/3.0/manual/api/reference/graph/create) と、 [Documentation の Graph Object](https://www.zabbix.com/documentation/3.0/manual/api/reference/graph/object#graph) を見てください。

## 終わりに
curl でベタ打ちしていますが、 実際に使う場合は itemid と color の部分は何かしら簡単なスクリプトで登録する前提です。
登録したいグラフがたくさんあったり、 ホストの組み合わせがたくさんある時には有効かと思います。


## 付録: 簡単なスクリプト

`prog.py --name "グラフ名" -x "TOKEN" 20001:FF0000 20002:00FF00 20003:0000FF`

と実行すると localhost の Zabbix に先ほどのグラフ作成のリクエストを送ってくれるスクリプトです。 色とかはもっと簡単に指定できるようにすると良い気がします..

```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
import sys
import argparse
import json
import urllib2

# create argparser
parser = argparse.ArgumentParser(description='Create Zabbix Graph easily...maybe..')
parser.add_argument('item', metavar="12345:RRGGBB", help="itemid:表示する色", nargs="+", action="append", type=str)
parser.add_argument('-x', metavar="012abc..32chars", help="auth token", type=str, required=True)
parser.add_argument('--name', metavar='"グラフ名称"', help="graph name", type=str, required=True)
parser.add_argument('--type', metavar='[norm|stack]', help="graph type", type=str, choices=['norm', 'stack'], default="norm")

args = parser.parse_args()
items = args.item[0]

# data template
data = {
    "jsonrpc": "2.0",
    "method": "graph.create",
    "params": {
        "name": args.name,
        "gitems": []
    },
    "auth": args.x,
    "id": 1
}

# create data
try:
    for item in items:
        (itemid, color) = item.split(':')
        data["params"]["gitems"].append({"itemid":itemid, "color":color})

    if args.type == "stack":
        data["params"]["graphtype"] = 1

    data_json = json.dumps(data)

except Exception as e:
    print("Error in JSON...");
    print(e)
    sys.exit(1)

# request
try:
    req = urllib2.Request(
        'http://localhost/zabbix/api_jsonrpc.php',
        data_json,
        {'Content-Type': 'application/json-rpc'}
    )
    result = urllib2.urlopen(req)
    result = json.loads(result.read())

except Exception as e:
    print("Error in API request...");
    print(e)
    sys.exit(1)

# handle result
if "error" in result:
    print("[Error] " + result["error"]["message"] + " / " + result["error"]["data"])
    sys.exit(1)
else:
    print("[Success] " + json.dumps(result["result"]))

sys.exit()
```



[^1]: 私のZabbix力が無さすぎるだけかも...