NagiosでのAPCのUPSのバッテリ監視3(交換予定日監視:NagiosのPlug-in作成)

APCUPSにネットワークカードを付けるとUPSの管理がネットワーク経由で出来るようになる。Nagiosを使った死活監視やバッテリー交換のチェックを出来るようにいろいろ考えてきた。

NagiosでのAPCのUPSのバッテリ監視

NagiosでのAPCのUPSのバッテリ監視2(Net-SNMPへのMIBの追加)
ここで問題は、バッテリの交換の通知をUPSから貰った段階では既にバッテリは寿命を迎えていると言うことである。通知を貰ってから交換用バッテリ購入の事務処理を行い発注をして到着するまでには最短でも1週間、長くなると2週間を超えることがあり、その段階で瞬停などの電源系のトラブルがあると機器は停止してしまう。
バッテリが寿命を迎える時期を明確に調べる方法はないため上記の危機を回避しようとすればバッテリを予防交換するしかない。
予防交換を行う契機として考えられるのは台帳でバッテリの交換時期を管理する方法が考えられるが、面倒だし忘れそうである。出来ればNagiosの仕組みの中で通知できるようにすれば管理もやりやすいと思った。
APCUPSのMIBの中にupsBasicBatteryLastReplaceDateと言う項目がある。バッテリ交換、最後にやったのはいつよ?と言う項目である。属性はSTRINGで内容は日付が入っている。ここの項目をチェックするようにした。
NagiosのPlug-inでcheck_snmpがあるがソースからインストールしたので手元にcheck_snmp.cがある。これの中を見てエッセンスをperl化して作ってみた。
作ったプログラムはcheck_upsbatday.pl
引数は -H IPアドレス -C コミュニティ -w WARNINGまでの経過日数 -c criticalまでの経過日数
戻りは
0:OK
1:WARNING
2:CRITICAL
である。
-1:unknownはめんどいのでやめた。

#!/usr/bin/perl
use Time::Local ;

$SNMPGET_PATH = "snmpget" ;

$community="" ;
$ip="" ;
$warning=0 ;
$critical=0 ;

$flg="" ;
foreach $dt (@ARGV){
        if($dt eq "-C"){
                $flg=$dt ;
        }elsif($dt eq "-H"){
                $flg=$dt ;
        }elsif($dt eq "-w"){
                $flg=$dt ;
        }elsif($dt eq "-c"){
                $flg=$dt ;
        }else{
                if($flg eq "-C"){
                        $community=$dt ;
                }elsif($flg eq "-H"){
                        $ip=$dt ;
                }elsif($flg eq "-w"){
                        $warning=$dt*86400 ;
                }elsif($flg eq "-c"){
                        $critical=$dt*86400 ;
                }
                $flg="" ;
        }
}

open( FILE, "$SNMPGET_PATH -c $community -v 1 $ip upsBasicBatteryLastReplaceDate.0 |");
$outdt="";

while ( <FILE> ){
    $outdt .= $_ ;
}

@splitdt=split(/"/,$outdt) ;
@ymd=split("/",$splitdt[1]) ;
if(length($ymd[2])<4){
        if($ymd[2]>90){
                $ymd[2]="19" . $ymd[2] ;
        }else{
                $ymd[2]="20" . $ymd[2] ;
        }
}

$olddt=timelocal(0,0,0,$ymd[1],$ymd[0]-1,$ymd[2]-1900) ;
$workdt="UPS BAT " ;
$workdt2="" ;
if(time-$warning > $olddt){
        if(time-$critical > $olddt){
                $workdt .= "CRITICAL | " ;
                $expr=2 ;
        }else{
                $workdt .= "WARNING | " ;
                $expr=1 ;
        }
}else{
        $workdt .= "OK | " ;
        $expr=0 ;
}
close( FILE );
print $workdt.$outdt ;
exit($expr) ;
1;

作成したファイルをnagiosディレクトリ配下のlibexecディレクトリに入れる。
nagios側の設定はetcディレクトリにあるcheck_command.cfgに以下を追加する。

define command{
        command_name    check_upsbatday
        command_line $USER1$/check_upsbatday.pl -H $HOSTADDRESS$ -C $ARG1$ -w $ARG2$ -c $ARG3$
        }

また、services.cfgに以下の定義を追加する。

# Generic service definition template for SNMP Cheeck Battery-replacdate
define service{
        name                            generic-check-APCUPS-battery-replacedate-service    ; The 'name' of this service template, referenced in other service definitions
        active_checks_enabled           1       ; Active service checks are enabled
        passive_checks_enabled          1       ; Passive service checks are enabled/accepted
        parallelize_check               1       ; Active service checks should be parallelized (disabling this can lead to major performance problems)
        obsess_over_service             1       ; We should obsess over this service (if necessary)
        check_freshness                 0       ; Default is to NOT check service 'freshness'
        notifications_enabled           1       ; Service notifications are enabled
        event_handler_enabled           1       ; Service event handler is enabled
        flap_detection_enabled          1       ; Flap detection is enabled
        process_perf_data               1       ; Process performance data
        retain_status_information       1       ; Retain status information across program restarts
        retain_nonstatus_information    1       ; Retain non-status information across program restarts

        register                        0       ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE, JUST A TEMPLATE!

        service_description             BATTERY-REP-DATE-SNMP
        is_volatile                     0
        check_period                    24x7
        max_check_attempts              3
        normal_check_interval           5
        retry_check_interval            1
        contact_groups                  nagios
        notification_interval           0
        notification_period             24x7
#        notification_options            w,u,c,r
        check_command                   check_upsbatday!public!730!760
        }

この設定では、upsBasicBatteryLastReplaceDateと現在の日付の差が730日(概ね2年)でWARNING、760日(概ね2年1ヶ月)でCRITICALを発生させるようにしている。また、Mailによる通知はOFFにしている。

このほかに、servies.cfgに監視対象のUPSのhost名を定義する。

define service{
        use                             generic-check-APCUPS-battery-replacedate-service
        host_name                       UPS007,UPS010,UPS011,UPS026,UPS027,UPS028,UPS029,UPS030,UPS031,UPS032,UPS033,UPS034,UPS035,UPS036,UPS037,UPS080
        }

UPSの番号が歯抜けなのはネットワークカードが入っていないUPSが大量にあるということです。どこか隠れた隅っこで人知れずすすり泣きながらバッテリー切れを訴えているかも知れないことを考えると胸が痛む。
たまにラウンドしているけど、こちらは運用管理体制強化が課題。
UPSに最初から付いているポートは独自仕様のRS232Cだけである。黒やら灰色の純正ケーブルを買わされるのも業腹だが、これだけネットワークが普及しているにもかかわらず、ネットワークポートを標準装備しないのは解せない。今の時代ネットワークボードに何万円も出させられて。
APCには全てのUPS製品にネットワークポートの標準装備を強く望む。
それともそんなことを望むのはうちだけかなぁ?

で、upsBasicBatteryLastReplaceDateの値に関してであるが、バッテリを交換した場合には交換した日付を手でUPSにセットする必要がある。
値をセットするには、IEとかFIREFOXを立ち上げて、該当のUPSのIPをURLの欄に入力してUPSにアクセスをする。ユーザ名とパスワードを入力した後、左側の[ Configuration ]を選択し、[ General Settings]配下のLast Battery Replacement:に新しい値(MM/DD/YYのフォーマット)をセットしてApplyボタンを押す。