Collection Hook

Collection Hookは、Collectionの登録、変更、削除時に実行されるカスタムスクリプトを作成できるサービスです。
例えば、外部のメトリックサーバとZabbixでデータを同期したい場合、Collection登録時に対応する管理ホストをZabbixに自動登録しておき、ReflectionでZabbixにメトリック転送する場合などが該当します。
Collectionのrun_scriptに紐づけることで実行されます。

Collection Hookが保有する属性

属性 概要 備考
name フックの名前を指定します。 ユニークである必要があります。
script カスタムスクリプトを記述します。 -

Note

カスタムスクリプトで参照できるパラメータは以下の通りです。ビルトイン関数や共通コンテキストも同様に利用可能です。
参照変数の内容を書き換えたい場合は、グローバル宣言を使用する必要があります。

Method Variable Description
POST collection POSTされたCollection辞書
PUT collection PUTされたCollection辞書(変更後)
PUT previous 変更前のCollection辞書
DELETE collection 削除するCollection辞書

サンプル

以下はCollection登録時にZabbixに管理ホストや監視アイテムを自動登録するカスタムスクリプトの例です。
Collectionが保有するcorrelation_infoを参照してホストを作成します。またZabbix側のホストグループIDやホストIDもcorrelation_infoに取り込んで後段のReflectionにも伝搬させることができます。correlation_infoを更新するためには先頭行のcollection変数へのglobal宣言が必要です。

- name: createHost
  script: |-
    global collection

    async def jsonrpc(token, method, **params):
        payload = MU(dict(jsonrpc="2.0", method=method, params=params, id=1, auth=token))
        r = await callout(url=collection["correlation_info"]["zabbix_url"],
                          method=POST,
                          headers={"Content-Type": "application/json-rpc"},
                          body=payload.dictionary)
        if r.error:
            raise Error(r.code, reason="Communication failure occurred")
        result = MU(json.loads(r.body))
        return result

    # Zabbix認証トークン取得
    r = await jsonrpc(None, "user.login", user=collection["correlation_info"]["zabbix_username"],
                                          password=collection["correlation_info"]["zabbix_password"])
    if r.error:
        raise Error(500, reason="Unable to get token", body=r.error.dictionary)
    token = r.result
    qprint("Zabbix Token: %r" % token)

    # ホストグループ登録
    r = await jsonrpc(token, "hostgroup.create", name=collection["correlation_info"]["zabbix_hostgroup"])
    # 重複登録の場合以外は例外発出
    if r.error and r.error.code != -32602:
        raise Error(500, reason="Unable to create host group", body=r.error.dictionary)

    # ホストグループID取得
    r = await jsonrpc(token, "hostgroup.get", output="extend", filter={"name": [collection["correlation_info"]["zabbix_hostgroup"]]})
    if r.error:
        raise Error(500, reason="Unable to retrieve host group", body=r.error.dictionary)

    groupid = r.result[0].groupid
    qprint("Host Group ID: %r" % groupid)

    # ホスト登録
    r = await jsonrpc(token, "host.create", host=collection["hostname"],
                                            interfaces=[{"type": 1, "main": 1,"useip": 1, "ip": collection["address"], "dns": "", "port": "10050"}],
                                            groups=[{"groupid": groupid}])
    # 重複登録の場合以外は例外発出
    if r.error and r.error.code != -32602:
        raise Error(500, reason="Unable to create host", body=r.error.dictionary)

    # ホストID取得
    r = await jsonrpc(token, "host.get", filter={"name": [collection["hostname"]]})
    if r.error:
        raise Error(500, reason="Unable to get host", body=r.error.dictionary)
    hostid = r.result[0].hostid
    qprint("Host ID: %r" % hostid)

    # 監視アイテム登録
    r = await jsonrpc(token, "item.create", name="tcpActiveOpens",
                                            key_="tcpActiveOpens",
                                            hostid=hostid,
                                            type=2,
                                            value_type=3)
    if r.error:
        raise Error(500, reason="Unable to create tcpActiveOpens item", body=r.error.dictionary)

    r = await jsonrpc(token, "item.create", name="tcpPassiveOpens",
                                            key_="tcpPassiveOpens",
                                            hostid=hostid,
                                            type=2,
                                            value_type=3)
    if r.error:
        raise Error(500, reason="Unable to create tcpPassiveOpens item", body=r.error.dictionary)

    for i in ["Gi1", "Gi2", "Gi3"]:
        r = await jsonrpc(token, "item.create", name="{}.traffic.in.bps".format(i),
                                                key_="{}.traffic.in.bps".format(i),
                                                hostid=hostid,
                                                type=2,
                                                value_type=0)
        if r.error:
            raise Error(500, reason="Unable to create {}.traffic.in.bps item".format(i), body=r.error.dictionary)

    r = await jsonrpc(token, "item.create", name="vmStatus",
                                            key_="vmStatus",
                                            hostid=hostid,
                                            type=2,
                                            value_type=3)
    if r.error:
        raise Error(500, reason="Unable to create vmStatus item", body=r.error.dictionary)

    r = await jsonrpc(token, "item.create", name="pingDelay",
                                            key_="pingDelay",
                                            hostid=hostid,
                                            type=2,
                                            value_type=0)
    if r.error:
        raise Error(500, reason="Unable to create vmStatus item", body=r.error.dictionary)

    collection["correlation_info"]["zabbix_hostgroupid"] = groupid
    collection["correlation_info"]["zabbix_hostid"] = hostid
    qprint(MU(collection).yaml_format)

Collection Hookのテストは、Collection組込みオブジェクトを利用してください。カスタムスクリプトにqprintを埋め込みREPLのdebug機能で出力確認すると効率的です。

>>> debug()↵
Disconnected the currently subscribed channel and connected to the debug channel ['xaas.southbound.channel']
debug channel connected
>>> c = await Collection.load("CSR1000v")↵
... await c.hook("createHost")↵
... ↵
Zabbix Token: '8cadc3fb0d9e971bfe101714b64ef148'
Host Group ID: '22'
Host ID: '10325'
↵
__FILE__: axis/handson/collections/CSR1000v.yml
__WORKSPACE__: axis-edge/hands-on_plugins
address: 192.168.2.200
collections:
- csr1000v
correlation_info:
  snmp_community: public
  vmid: 75CE72DHP742RGQCMLI1MCRFK8I1KRNS
  vmware_endpoint: http://localhost:8697
  vmware_password: Qmonus!2021
  vmware_username: qmonus
  zabbix_host: localhost
  zabbix_hostgroup: qmonus-example
  zabbix_hostgroupid: '22'
  zabbix_hostid: '10325'
  zabbix_password: zabbix
  zabbix_port: 10051
  zabbix_url: http://localhost:80/api_jsonrpc.php
  zabbix_username: Admin
enable: true
hostname: CSR1000v
target_id: e22ea82a612311eb92f7acde48001122
update: '2021-02-08T10:22:17.167850+09:00'
version: 9
>>> debug(False)↵
debug channel disconnected
>>>

Note

上記スクリプトをお試しする場合は、Zabbixサーバが必要です。
docker pull zabbix/zabbix-appliance
docker run --name zabbix-appliance -t -p 10051:10051 -p 80:80 -d zabbix/zabbix-appliance