読者です 読者をやめる 読者になる 読者になる

F@N Ad-Tech Blog

株式会社ファンコミュニケーションズ nend・nex8のエンジニア・技術ブログ

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

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

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

CactiCLIツールについて

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

[shell] [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 [/shell]

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

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

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

[shell] [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.)

[/shell]

前提

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

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.ホストの登録

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

[shell]

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

HostTemplate=

CactiCLIツールが置いてあるパスへ移動

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} [/shell]

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

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

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

[shell]

登録したホストのデバイス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 [/shell]

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

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

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

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

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

[shell]

 「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 [/shell]

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

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

[shell]

 「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 [/shell]

これで/や/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(抜粋)

[html] <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> [/html]

resource/script_server/host_disk.xml(抜粋)

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

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

[shell] [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) [/shell]

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

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

[html] <script_path>|path_cacti|/scripts/ss_host_disk.php</script_path> [/html]

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

[html] "description"   => ".1.3.6.1.2.1.25.2.3.1.3", [/html]

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

[shell] [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 [/shell]

完成系

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

[shell]

!/bin/bash

コマンドライン引数でIPアドレスとホスト名を指定します。

IPADDR=$1 HOSTNAME=$2

下記は各自の環境に合わせてください。

CLIPATH="/home/www/cacti/cli" COMMUNITY="test-community" HostTemplate="test(web)"

CactiCLIツールが置いてあるパスへ移動

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 &quot;Interface - Traffic (bits/sec)&quot; | awk '{print $1}'

SNMP - Interface Statistics」 というSNMP Query IDを取得

TrafficSnmpQueryId=php add_graphs.php --list-snmp-queries | grep &quot;SNMP - Interface Statistics&quot; | 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 &quot;In/Out Bits (64-bit Counters)&quot; | 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 &quot;Host MIB - Available Disk Space&quot; | awk '{print $1}'

SNMP - Get Mounted Partitions」 というSNMP Query IDを取得

UsedSpaceSnmpQueryId=php add_graphs.php --list-snmp-queries | grep &quot;SNMP - Get Mounted Partitions&quot; | awk '{print $1}'

「Available Disk Space」 というSNMP Query Type IDを取得

UsedSpaceQueryTypeId=php -q add_graphs.php --snmp-query-id=${UsedSpaceSnmpQueryId} --list-query-types | grep &quot;Available Disk Space&quot; | 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 &quot;s/^.* STRING: //&quot; 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 [/shell]

実行例

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

[shell] [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) [/shell]

終わりに

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

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