Cactiへホスト登録するスクリプトを作る


Cactiに監視対象のホストを登録する時は、通常はブラウザで行います。
数台ならいいのですが、数十台数百台となってくると結構なクリック量で肩は凝るし、目もつらいです。

実はCactiならCLIを使っていろいろできるらしいのです。
コマンドだけでホスト登録可能かな?と試した結果、コマンドだけでできちゃいました。
そこでお試しで作成したホスト登録スクリプトを公開します。

CactiのCLIツールについて

Cactiをインストールすると自動的にphpで実行可能なコマンドラインツールもインストールされます。
cactiディレクトリ直下にcliディレクトリがあるはずです。

[n_watanabe@cacti ~]$ ls  -1 /home/www/cacti/cli/
add_data_query.php
add_device.php
add_graphs.php
add_graph_template.php
add_perms.php
add_tree.php
convert_innodb.php
copy_user.php
host_update_template.php
import_template.php
poller_data_sources_reapply_names.php
poller_graphs_reapply_names.php
poller_output_empty.php
poller_reindex_hosts.php
rebuild_poller_cache.php
repair_database.php
repair_templates.php
structure_rra_paths.php
upgrade_database.php

今回のスクリプト内では、その中から以下のCacti純正ツールを利用しました。

  • add_graph_template.php
  • add_graphs.php
  • add_device.php

なお、ほとんどのツールは、–helpオプションを持っているので使い方を確認できます。

[n_watanabe@cacti cli]$ php add_graphs.php --help
Add Graphs Script 1.2, Copyright 2008 - The Cacti Group

A simple command line utility to add graphs in Cacti

usage: add_graphs.php --graph-type=[cg|ds] --graph-template-id=[ID]
--host-id=[ID] [--graph-title=title] [graph options] [--force] [--quiet]

For cg graphs:
[--input-fields="[data-template-id:]field-name=value ..."] [--force]

--input-fields  If your data template allows for custom input data, you may specify that
here.  The data template id is optional and applies where two input fields
have the same name.
--force         If you set this flag, then new cg graphs will be created, even though they
may already exist

For ds graphs:
--snmp-query-id=[ID] --snmp-query-type-id=[ID] --snmp-field=[SNMP Field] --snmp-value=[SNMP Value]

[--graph-title=]       Defaults to what ever is in the graph template/data-source template.

[--reindex-method=]    the reindex method to be used for that data query
if data query already exists, the reindex method will not be changed
0|None   = no reindexing
1|Uptime = Uptime goes Backwards (Default)
2|Index  = Index Count Changed
3|Fields = Verify all Fields
List Options:
--list-hosts
--list-graph-templates [--host-template-id=[ID]]
--list-input-fields --graph-template-id=[ID]
--list-snmp-queries
--list-query-types  --snmp-query-id [ID]
--list-snmp-fields  --host-id=[ID] [--snmp-query-id=[ID]]
--list-snmp-values  --host-id=[ID] [--snmp-query-id=[ID]] --snmp-field=[Field]

'cg' graphs are for things like CPU temp/fan speed, while
'ds' graphs are for data-source based graphs (interface stats etc.)

前提

ホストテンプレートは作成済みという前提でいきます。
「ホスト登録」「ホストテンプレートを元にグラフ作成」を一発で行えるようにするのが今回の目的です。
例えば今回の例では、下記のようなホストテンプレートを使います。

host_template_graph-type

個々の項目は気にしないでいいのですが、重要なのはAssociated Graph TemplatesAssociated Data Queriesの2種類あることです。
そしてそれに基づいて、Cacti付属のグラフ作成スクリプトであるadd_graphs.phpのオプションが変わります。
–graph-typeの指定でcgとdsの2種類があります。

Associated Graph Templatesで作成されるグラフ

こちらは明解です。
1つのグラフテンプレートで1つのグラフが作成されます。

Associated Data Queriesで作成されるグラフ

こちらはやや理解が難しいです。
1つのデータクエリーで複数のグラフが作成される可能性があります。

例として、ネットワークインターフェースを挙げます。
複数のインターフェースを検出すると、それぞれ別のグラフが作成されます。(eth0,eth1など)
また、1つのインターフェースでもモニターする項目が違うと別のグラフが作成されます。(トラフィック量,エラー数など)

したがって、eth0のトラフィックグラフ、eth0のエラー数グラフ、eth1のトラフィックグラフ、eth1のエラー数グラフなどが作成される可能性があります。

Step1.ホストの登録

まず、ホストの登録です。

# 適用したいホストテンプレート名を指定
HostTemplate=

# CactiのCLIツールが置いてあるパスへ移動
cd ${CLIPATH}

# ホストテンプレートIDを取得
HostTemplateId=`php add_device.php --list-host-templates | grep ${HostTemplate} | awk '{print $1}'`

# ホストの登録
php add_device.php --description=${HOSTNAME} --ip=${IPADDR} --template=${HostTemplateId}

これで適切なホストテンプレートに関連付けられたホストの登録ができました。
しかしまだグラフは作成されていない状態です。

Step2.graph-type=cgのグラフを作成する

登録したホストに対して、グラフを作成します。

# 登録したホストのデバイスIDを取得
DeviceId=`php add_tree.php --list-trees --list-hosts | grep ${HOSTNAME} | awk '{print $1}'`

# ホストテンプレートに関連づいた各グラフテンプレートのグラフを作成
for GraphTemplateId in `php add_graphs.php --list-graph-templates --host-template-id=${HostTemplateId} | sed '1d' | sed '$d' | awk '{print $1}'`
do
  php add_graphs.php --host-id=${DeviceId} --graph-type=cg --graph-template-id=${GraphTemplateId}
done

これで–graph-type=cg部分のグラフは作成できました。

Step3.graph-type=dsのグラフを作成する

ここから少し難しくなってきます。
おそらく各自の環境に合わせた修正が必要になってきます。

ここは各自の環境に合わせて、適宜調整していただく必要があります。

Step3-1.Trafficグラフを作成する

# 「Interface - Traffic (bits/sec)」 というグラフテンプレートのIDを取得
TrafficGraphTemplateId=`php add_graphs.php --list-graph-templates | grep -w "Interface - Traffic (bits/sec)" | awk '{print $1}'`

# 「SNMP - Interface Statistics」 というSNMP Query IDを取得
TrafficSnmpQueryId=`php add_graphs.php --list-snmp-queries | grep "SNMP - Interface Statistics" | awk '{print $1}'`

# 「In/Out Bits (64-bit Counters)」 というSNMP Query Type IDを取得
TrafficQueryTypeId=`php -q add_graphs.php --snmp-query-id=${TrafficSnmpQueryId} --list-query-types | grep "In/Out Bits (64-bit Counters)" | awk '{print $1}'`

# インターフェースの数だけ、グラフを作成。ただし、loopbackを除外するために --snmp-value=ethernetCsmacdでフィルタ
php add_graphs.php --host-id=${DeviceId} --graph-type=ds --graph-template-id=${TrafficGraphTemplateId} --snmp-query-id=${TrafficSnmpQueryId} --snmp-query-type-id=${TrafficQueryTypeId} --snmp-field=ifType --snmp-value=ethernetCsmacd

これでeth0,eth1等のトラフィックグラフが作成できました。

Step3-2.Disk使用量のグラフを作成する

# 「Host MIB - Available Disk Space」 というグラフテンプレートのIDを取得
UsedSpaceGraphTemplateId=`php add_graphs.php --list-graph-templates | grep "Host MIB - Available Disk Space" | awk '{print $1}'`

# 「SNMP - Get Mounted Partitions」 というSNMP Query IDを取得
UsedSpaceSnmpQueryId=`php add_graphs.php --list-snmp-queries | grep "SNMP - Get Mounted Partitions" | awk '{print $1}'`

# 「Available Disk Space」 というSNMP Query Type IDを取得
UsedSpaceQueryTypeId=`php -q add_graphs.php --snmp-query-id=${UsedSpaceSnmpQueryId} --list-query-types | grep "Available Disk Space" | awk '{print $1}'`

# ディスクパーティションの数だけ、グラフを作成。
PRE_IFS=$IFS
IFS=$'\n'
for Partition in `snmpwalk -c ${COMMUNITY} -v 2C ${IPADDR} .1.3.6.1.2.1.25.2.3.1.3 | sed -e "s/^.* STRING: //"`
do
php add_graphs.php --host-id=${DeviceId} --graph-type=ds --graph-template-id=${UsedSpaceGraphTemplateId} --snmp-query-id=${UsedSpaceSnmpQueryId} --snmp-query-type-id=${UsedSpaceQueryTypeId} --snmp-field=hrStorageDescr --snmp-value="${Partition}"
done
IFS=$PRE_IFS

これで/や/bootなどのパーティションごとにディスク使用量のグラフが作成されました。

Step3.補足説明

snmp-fieldとsnmp-valueについても説明しておきます。
これはフィルタ機能であり、snmp-field(項目)にsnmp-value(値)が合致したものだけグラフ作成の対象とされます。

snmp-fieldに何を指定できるかですが、それはDataQuery内で定義されたXMLファイル内に書いてあります。

dataquery_interface
dataquery_hostdisk

それぞれのXMLファイルを見てみると、ifTypehrStorageDescrが定義されています。

resource/snmp_queries/interface.xml(抜粋)

<ifType>
<name>Type</name>
<method>walk</method>
<source>value</source>
<direction>input</direction>
<oid>.1.3.6.1.2.1.2.2.1.3</oid>
</ifType>

resource/script_server/host_disk.xml(抜粋)

<script_path>|path_cacti|/scripts/ss_host_disk.php</script_path>
<hrStorageDescr>
<name>Description</name>
<direction>input</direction>
<query_name>description</query_name>
</hrStorageDescr>

以下でifTypeのValueにどんな値が取りうるのか確認可能です。

[n_watanabe@cacti cacti]$ snmpwalk -c test-community -v 2C 192.168.1.5 .1.3.6.1.2.1.2.2.1.3
IF-MIB::ifType.1 = INTEGER: softwareLoopback(24)
IF-MIB::ifType.2 = INTEGER: ethernetCsmacd(6)
IF-MIB::ifType.3 = INTEGER: ethernetCsmacd(6)

今回はsoftwareLoopback(ループバックインターフェース)は不要なので、ethernetCsmacd(eth0,eth1)でフィルタするようにしました。

host_disk.xmlの方にはSNMPのOIDが書いていないのですが、よく見るとスクリプトが指定されています。

<script_path>|path_cacti|/scripts/ss_host_disk.php</script_path>

このスクリプトファイルを見ると、やはりOIDが指定されています。

"description"   => ".1.3.6.1.2.1.25.2.3.1.3",

以下でhrStorageDescrのValueにどんな値が取りうるのか確認可能です。

[n_watanabe@cacti cacti]$ snmpwalk -c test-community -v 2C 192.168.1.5 .1.3.6.1.2.1.25.2.3.1.3
HOST-RESOURCES-MIB::hrStorageDescr.1 = STRING: Physical memory
HOST-RESOURCES-MIB::hrStorageDescr.3 = STRING: Virtual memory
HOST-RESOURCES-MIB::hrStorageDescr.6 = STRING: Memory buffers
HOST-RESOURCES-MIB::hrStorageDescr.7 = STRING: Cached memory
HOST-RESOURCES-MIB::hrStorageDescr.10 = STRING: Swap space
HOST-RESOURCES-MIB::hrStorageDescr.31 = STRING: /
HOST-RESOURCES-MIB::hrStorageDescr.35 = STRING: /dev/shm
HOST-RESOURCES-MIB::hrStorageDescr.36 = STRING: /boot

完成系

下記のようなcacti_add_host.shというシェルスクリプトを作成しました。

#!/bin/bash

# コマンドライン引数でIPアドレスとホスト名を指定します。
IPADDR=$1
HOSTNAME=$2

# 下記は各自の環境に合わせてください。
CLIPATH="/home/www/cacti/cli"
COMMUNITY="test-community"
HostTemplate="test(web)"

# CactiのCLIツールが置いてあるパスへ移動
cd ${CLIPATH}

# ホストテンプレートIDを取得
HostTemplateId=`php add_device.php --list-host-templates | grep ${HostTemplate} | awk '{print $1}'`

# ホストの登録
php add_device.php --description=${HOSTNAME} --ip=${IPADDR} --template=${HostTemplateId}

# 登録したホストのデバイスIDを取得
DeviceId=`php add_tree.php --list-trees --list-hosts | grep ${HOSTNAME} | awk '{print $1}'`

# ホストテンプレートに関連づいた各グラフテンプレートのグラフを作成
for GraphTemplateId in `php add_graphs.php --list-graph-templates --host-template-id=${HostTemplateId} | sed '1d' | sed '$d' | awk '{print $1}'`
do
php add_graphs.php --host-id=${DeviceId} --graph-type=cg --graph-template-id=${GraphTemplateId}
done

### Trafficグラフ

# 「Interface - Traffic (bits/sec)」 というグラフテンプレートのIDを取得
TrafficGraphTemplateId=`php add_graphs.php --list-graph-templates | grep -w "Interface - Traffic (bits/sec)" | awk '{print $1}'`

# 「SNMP - Interface Statistics」 というSNMP Query IDを取得
TrafficSnmpQueryId=`php add_graphs.php --list-snmp-queries | grep "SNMP - Interface Statistics" | awk '{print $1}'`

# 「In/Out Bits (64-bit Counters)」 というSNMP Query Type IDを取得
TrafficQueryTypeId=`php -q add_graphs.php --snmp-query-id=${TrafficSnmpQueryId} --list-query-types | grep "In/Out Bits (64-bit Counters)" | awk '{print $1}'`

# インターフェースの数だけ、グラフを作成。ただし、loopbackを除外するために --snmp-value=ethernetCsmacdでフィルタ
php add_graphs.php --host-id=${DeviceId} --graph-type=ds --graph-template-id=${TrafficGraphTemplateId} --snmp-query-id=${TrafficSnmpQueryId} --snmp-query-type-id=${TrafficQueryTypeId} --snmp-field=ifType --snmp-value=ethernetCsmacd

### Disk使用量グラフ

# 「Host MIB - Available Disk Space」 というグラフテンプレートのIDを取得
UsedSpaceGraphTemplateId=`php add_graphs.php --list-graph-templates | grep "Host MIB - Available Disk Space" | awk '{print $1}'`

# 「SNMP - Get Mounted Partitions」 というSNMP Query IDを取得
UsedSpaceSnmpQueryId=`php add_graphs.php --list-snmp-queries | grep "SNMP - Get Mounted Partitions" | awk '{print $1}'`

# 「Available Disk Space」 というSNMP Query Type IDを取得
UsedSpaceQueryTypeId=`php -q add_graphs.php --snmp-query-id=${UsedSpaceSnmpQueryId} --list-query-types | grep "Available Disk Space" | awk '{print $1}'`

# ディスクパーティションの数だけ、グラフを作成。
PRE_IFS=$IFS
IFS=$'\n'
for Partition in `snmpwalk -c ${COMMUNITY} -v 2C ${IPADDR} .1.3.6.1.2.1.25.2.3.1.3 | sed -e "s/^.* STRING: //"`
do
php add_graphs.php --host-id=${DeviceId} --graph-type=ds --graph-template-id=${UsedSpaceGraphTemplateId} --snmp-query-id=${UsedSpaceSnmpQueryId} --snmp-query-type-id=${UsedSpaceQueryTypeId} --snmp-field=hrStorageDescr --snmp-value="${Partition}"
done
IFS=$PRE_IFS

実行例

IPアドレス=192.168.1.5、ホスト名=testweb01を登録した時の実行例です。

[n_watanabe@cacti ~]$ ./cacti_add_host.sh 192.168.1.5 testweb01
Adding testweb01 (192.168.1.5) as "test(web)" using SNMP v2 with community "test-community"
Success - new device-id: (930)
Graph Added - graph-id: (26068) - data-source-ids: (33173, 33174, 33175)
Graph Added - graph-id: (26069) - data-source-ids: (33176, 33177, 33178)
Graph Added - graph-id: (26070) - data-source-ids: (33179)
Graph Added - graph-id: (26071) - data-source-ids: (33180)
Graph Added - graph-id: (26072) - data-source-ids: (33181)
Graph Added - graph-id: (26073) - data-source-ids: (33182)
Graph Added - graph-id: (26074) - data-source-ids: (33183)
Graph Added - graph-id: (26075) - data-source-ids: (33184)
Graph Added - graph-id: (26076) - data-source-ids: (33185)
Graph Added - graph-id: (26077) - data-source-ids: (33186)
Graph Added - graph-id: (26078) - data-source-ids: (33187, 33188, 33189, 33190)
Graph Added - graph-id: (26079) - data-source-ids: (33191, 33192, 33193, 33194, 33195, 33196, 33197, 33198)
Graph Added - graph-id: (26080) - data-source-ids: (33199, 33199)
Graph Added - graph-id: (26081) - data-source-ids: (33200, 33200)
Graph Added - graph-id: (26082) - data-source-ids: (33201, 33201)
Graph Added - graph-id: (26083) - data-source-ids: (33202, 33202)
Graph Added - graph-id: (26084) - data-source-ids: (33203, 33203)
Graph Added - graph-id: (26085) - data-source-ids: (33204, 33204)
Graph Added - graph-id: (26086) - data-source-ids: (33205, 33205)
Graph Added - graph-id: (26087) - data-source-ids: (33206, 33206)
Graph Added - graph-id: (26088) - data-source-ids: (33207, 33207)
Graph Added - graph-id: (26089) - data-source-ids: (33208, 33208)

終わりに

残念ながら、完全に汎用的なスクリプトは作成できませんでした。
graph-type=dsの部分が無いホストテンプレートなら、ほぼそのまま使えると思いますが、ある場合は各現場で調整していただく必要があります。

とはいえ、ホストの追加が頻繁に発生する現場なら、こういったスクリプトを作成する価値はあるのではないでしょうか。
参考にしていただければ幸いです。

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*