Contents
Go
を使ってロード可能モジュール(Loadable modules)を作ってみます。Zabbix3.2のモジュールを作った時に少しハマったのでメモしておきます 🙂
環境
項目 | バージョン |
---|---|
OS | CentOS 7.2 |
Zabbix | 3.2 |
Go | 1.8.1 |
GoのZabbixモジュールアダプタ
g2z
Zabbixのネイティブモジュールが作成できるGoバイディングである g2z
を使用します。
ドキュメント
インストール
パッケージインストール
(1) 必要なパッケージをインストールします。
1 2 |
[root@localhost ~]# yum -y install git gcc |
g2zインストール
(1) g2z
をインストールします。Zabbixは3.2を使うのでバージョン3を指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@localhost ~]# go get -v gopkg.in/cavaliercoder/g2z.v3 gopkg.in/cavaliercoder/g2z.v3 # gopkg.in/cavaliercoder/g2z.v3 In file included from $WORK/gopkg.in/cavaliercoder/g2z.v3/_obj/_cgo_export.c:3:0: go/src/gopkg.in/cavaliercoder/g2z.v3/module.go: 関数 ‘append_metric’ 内: go/src/gopkg.in/cavaliercoder/g2z.v3/module.go:44:2: 警告: 組み込み関数 ‘memcpy’ の互換性がない暗黙的な宣言です [デフォルトで有効] memcpy(list, n, sizeof(ZBX_METRIC)); ^ # gopkg.in/cavaliercoder/g2z.v3 go/src/gopkg.in/cavaliercoder/g2z.v3/module.go: 関数 ‘append_metric’ 内: go/src/gopkg.in/cavaliercoder/g2z.v3/module.go:44:2: 警告: 組み込み関数 ‘memcpy’ の互換性がない暗黙的な宣言です [デフォルトで有効] memcpy(list, n, sizeof(ZBX_METRIC)); ^ |
g2zの修正
修正しなくてはいけない理由
Zabbix 3.2から ZBX_MODULE_API_VERSION_ONE
から ZBX_MODULE_API_VERSION
に変更されています。
そのため、g2zをインストールしてモジュールをビルドしZabbixへ組み込んだあとに起動すると以下のエラーが発生します。
1 2 3 4 |
5603:20170529:003940.573 using configuration file: /etc/zabbix/zabbix_agentd.conf 5603:20170529:003940.577 unsupported module "example.so" version: 1 <- サポートしていないバージョンなので起動できない 5603:20170529:003940.577 loading modules failed, exiting... |
Zabbixのソースコードを見てみましょう。
1 2 3 4 5 |
[root@localhost SOURCES]# grep -n 'ZBX_MODULE_API_VERSION' ./zabbix-3.2.6/include/module.h 29:#define ZBX_MODULE_API_VERSION 2 <- バージョンが 2 になっていることが確認できます 32:#define ZBX_MODULE_API_VERSION_ONE ZBX_MODULE_API_VERSION <- 古いのは新しいので上書きされています 35:/* #if ZBX_MODULE_API_VERSION == X */ |
3.2以上でロード可能モジュールを開発する場合は、g2zでもこの修正が必要になります。
修正手順
(1) g2zの module.h
の ZBX_MODULE_API_VERSION
を 2
に修正します。
1 2 3 4 |
[root@localhost ~]# vi go/src/gopkg.in/cavaliercoder/g2z.v3/module.h (snip) #define ZBX_MODULE_API_VERSION_ONE 2 |
これが、一番簡単な修正方法かと思います。
または module.h
に ZBX_MODULE_API_VERSION
を新しく追加して go/src/gopkg.in/cavaliercoder/g2z.v3/module.go
の zbx_module_api_version
関数内を修正しても大丈夫だと思います。
1 2 3 4 5 |
//export zbx_module_api_version func zbx_module_api_version() int { return C.ZBX_MODULE_API_VERSION_ONE <- ここ } |
ちなみに、本家にはプルリクがきている模様
モジュールのビルド及び組み込み
ここでは、g2zの例にあるソースをビルドしてZabbix Agentへ組み込んでみます。
(1) 以下のソースコードを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package main import ( "github.com/cavaliercoder/g2z" "strings" ) func main() { panic("THIS_SHOULD_NEVER_HAPPEN") } func init() { g2z.RegisterStringItem("go.echo", "Hello,world", Echo) } func Echo(request *g2z.AgentRequest) (string, error) { return strings.Join(request.Params, " "), nil } |
(2) ビルドします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[root@localhost ~]# go build -buildmode=c-shared -o example.so example.go # gopkg.in/cavaliercoder/g2z.v3 In file included from $WORK/gopkg.in/cavaliercoder/g2z.v3/_obj/_cgo_export.c:3:0: go/src/gopkg.in/cavaliercoder/g2z.v3/module.go: 関数 ‘append_metric’ 内: go/src/gopkg.in/cavaliercoder/g2z.v3/module.go:44:2: 警告: 組み込み関数 ‘memcpy’ の互換性がない暗黙的な宣言です [デフォルトで有効] memcpy(list, n, sizeof(ZBX_METRIC)); ^ # gopkg.in/cavaliercoder/g2z.v3 go/src/gopkg.in/cavaliercoder/g2z.v3/module.go: 関数 ‘append_metric’ 内: go/src/gopkg.in/cavaliercoder/g2z.v3/module.go:44:2: 警告: 組み込み関数 ‘memcpy’ の互換性がない暗黙的な宣言です [デフォルトで有効] memcpy(list, n, sizeof(ZBX_METRIC)); ^ |
(3) モジュールを任意の場所へ保存します。ここでは /etc/zabbix/modules
配下へ保存します。
1 2 3 4 |
[root@localhost ~]# mkdir /etc/zabbix/modules [root@localhost ~]# mv example.so /etc/zabbix/modules/ |
(4) Zabbix Agentへ組み込みます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[root@localhost ~]# vi /etc/zabbix/zabbix_agentd.conf (snip) ### Option: LoadModulePath # Full path to location of agent modules. # Default depends on compilation options. # # Mandatory: no # Default: # LoadModulePath=${libdir}/modules LoadModulePath=/etc/zabbix/modules ### Option: LoadModule # Module to load at agent startup. Modules are used to extend functionality of the agent. # Format: LoadModule=<module.so> # The modules must be located in directory specified by LoadModulePath. # It is allowed to include multiple LoadModule parameters. # # Mandatory: no # Default: # LoadModule= LoadModule=example.so |
(5) Zabbix Agentを起動します。
1 2 3 4 5 6 7 |
[root@localhost ~]# systemctl start zabbix-agent [root@localhost ~]# systemctl status zabbix-agent ● zabbix-agent.service - Zabbix Agent Loaded: loaded (/usr/lib/systemd/system/zabbix-agent.service; disabled; vendor preset: disabled) Active: active (running) since 月 2017-05-29 00:50:05 JST; 1min 59s ago (snip) |
動作確認
(1) 動作確認をしてみます。
1 2 3 |
[root@localhost ~]# zabbix_get -s 127.0.0.1 -k 'go.echo['test', 'hoge']' test hoge |
(2) Discoveryのソースコード例を組み込んで実行してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@localhost ~]# zabbix_get -s 127.0.0.1 -k 'go.discovery' { "data":[ { "{#INDEX}":"0"}, { "{#INDEX}":"1"}, { "{#INDEX}":"2"}, { "{#INDEX}":"3"}, { "{#INDEX}":"4"}]} |
これで、3.2のモジュールが開発できるようになりました 🙂
(独り言)3.4はいつでるんやろ…