30.UPSで停電克服計画(2004/03/21)

30.1.格安でUPSゲット!!するも、Linuxで使えないだと!?


UPS(無停電電源装置)って、すごい憧れの品でねぇ。
初代サーバを運用してたときも、すげぇ欲しくてヤフオクなどを探し回ってたんだけど、どれも高くて。
しかし、近所のSHOPでOMRON製のBX50LSという新品のUPSを偶然格安で見かけ。(6,800円)
速攻で購入しちゃいました。
「いやぁ〜、良い買い物したなぁ」なんて思いながら、箱を開けると、本体とシリアルケーブル等々が入っており。
もちろん、説明書をマジマジと読みます。
するとですね、意外な事実が判明しました。

付属のシリアルケーブルがNT用だってこと…。

まさに、がびーん!!って感じですよ。
何で、シリアルケーブルがOS依存なのか、訳分かりません。
しかも、このLinux用とやらのシリアルケーブル、OMRONの直販サイトで5000円弱…。
もう一台、UPS買えるやんけ…。
やってられません、マジで。
そんなわけで、OMRON製の『Power Assistant』という自動シャットダウンソフトは使えないようです。
う〜ん…。
されど、OMRON、そんな貧乏なユーザを見捨てたりはしません。
説明書には、こんな文章が書いてありました。

『仕様に合わせてお客様が独自にシステムを開発されることで、
 停電時の処理を自動化できます』

しかも、シリアルケーブルのPINと信号の関係図も添えて。
やるな、OMRON。
これは、「オマエみたいなヤツは自力で何とかしてくれたまへ」という愛のあるメッセージだと受け取りました。
そんなわけで、シリアルケーブルを調査することにしました。
30.2.付属のNT用シリアルケーブルを調べる

さて、まずはケーブルのことを調べてみましょう。
付属のNT用シリアルケーブルは、説明書より次のような仕様になってます。(ちなみにRS-232Cインタフェースの仕様も載せてみた)

付属のNT用シリアルケーブル仕様 RS-232Cインタフェース仕様
ピン番号信号名ピン配置
1FG

−−−−−−−−−−−−−−−
|  5 4 3 2 1  |
 |           |
  | 9 8 7 6 |
   −−−−−−−−−
2BU
3BU
4COM
5BL
6BS
7COM
8NC
9NC
              
ピン番号信号名信号方向信号の意味
1CD入力Carrier Detect
2RD入力Receive Data
3TD出力Transmit Data
4DTR出力Data Terminal Ready
5SGSignal Ground
6DSR入力Data Set Ready
7RTS出力Request to Send
8CTS入力Clear to Send
9RIRing Indicator(Open)
んで、テスターを使って付属のNT用シリアルケーブルのUPS側とPC側の配線を調べました。 結果は下表。(ちなみに、UPS側は付属シリアルケーブルの信号名、PC側はRS-232Cの信号名で表しています)
UPS側PC側
FGnot connected
BUCTS
RTS
BUnot connected
COMTD
BLCD
RTS
BSDTR
COMDSR
NCnot connected
NCnot connected
説明書によると、停電時にはBUとCOMが繋がり、バッテリー低下時にはBLとCOMが繋がるらしいです。 このことから、BUと繋がっているCTSをモニターすれば停電、BLと繋がっているCDをモニターすればバッテリー低下を確認できそうです。 また、説明書には停電、バッテリー低下信号を負(−)に設定するように書かれており、 停電時、バッテリー低下時はCOMに繋がるんで、COMを負(−)にしとけば良さそうです。 んじゃ、COMを負(−)にするにはどーすればいいか? COMに繋がっているのはTDとDSRで、このうちUPSに出力できる信号はTDです。(DSRは入力なんで) てなわけで、TDを負(−)にすればCOMは負(−)になります。 これで、停電時 or バッテリー低下時にBU or BLがCOMと繋がったとき、負(−)になります。 もちろん、これだけではダメですよ。 COMと繋がってないときはBUとBLは正(+)にしとかないと、停電 or バッテリー低下が検出できません。 で、BUとBLに繋がっているCTS、CDはそれぞれ入力(モニター用)なので、RTSを正(+)にしてBUとBLを正(+)にしましょう。 これだけわかれば、あとはしめたモノですが、もう一つ調べにゃならんことがありますです。 それは、PCがシャットダウンしちゃえば、UPSの電源も切ってよいってこと。 バッテリーが空になるまで、放っておくってのも手なのだが、なーんか勿体無いじゃん。 というわけで、UPSの電源を切る信号を探す必要があります。 で、コレも実は説明書に書いてあるわけで。^^; UPSの電源を切るには、BSを正(+)にすればいいみたい。 このBSに繋がっているのはDTRなんで、PCがシャットダウン処理後にDTRを正(+)にすればよいのです。(^^)v いやぁ、完璧、完璧。 しかし、実はこのDTRの設定が後に悲劇を招くことになるのです…。(それは後述) そんなわけで、結果をまとめると、 ということになります。 あとは、これらを監視するソフトを探してくればよいわけです。
30.3.初代、逝く。

で、ネット徘徊してて見つけたのが、genpower というソフト。
その筋のユーティリティとしては、有名なモノらしい。
これをインストールして、自動シャットダウン実験をすることにしました。
今回、実験機になっていただくのは初代サーバであるVineserver君。(OSはVine Linux 2.1.5)
この目的のために、暫くの間、部屋の隅で埃かぶっていたと言っても過言ではありません。
というわけで、さっそく活躍していただきましょう。

Vineserver君
ひさびさの活躍だぁ〜。雄姿を見せろぉ〜。


まずは genpower をダウンロードして、展開します。(今回はgenpower-1.0.2.tar.gzを取ってきました)

$ tar zxvf genpower-1.0.2.tar.gz

でOK。
そして展開後、genpowerd.h をBX50LSの仕様に合わせて編集します。
編集内容は、先ほど調べた信号の仕様に合わせて記述するだけです。
genpower.docs の2.2.2.3.以降を見ると、詳しく説明が書いてあり、
DTRはTIOCM_DTR、RTSはTIOCM_RTS、CTSはTIOCM_CTSというMacroを使えばよいことがわかります。
CDはDCDなので、TIOCM_CAR、TDは見当たらないので設定不要でしょう。
正は0、負は1を表すので、調べた結果から

/* OMRON BX50LS */
 {7, "omron-bx50ls",   {TIOCM_RTS,0}, {TIOCM_DTR,1},  5, {TIOCM_CTS,0}, {TIOCM_CAR,0}, {0,0}},

を {-1, NULL} の前(105から108行目付近)に記述すればOKです。 ちなみに {TIOCM_DTR,1} の後の”5”は、kill time を表します。 genpowerd.h の編集が終わったら、メイクしてインストールします。 あっ、ここからはすべてroot権限で作業してると思ってください。
$ cd genpower-1.0.2
$ make
$ make install

インストール完了すると、/sbin 以下にgenpowerd、/etc 以下にgenpowerfail が入ります。 /sbin/genpowerd はデーモンなんで後で起動するとして、/etc/genpowerfail を編集しときます これ、UPSの状態を参照して指定処理を実行するスクリプトなんだけど、中身を見ると、shutdown -r となっており、このままでは電源が切れません。(笑) てなわけで、”shutdown -r ”の箇所はすべて”shutdown -h ”と修正。 ちなみに停電(電源異常)時には、”+2”オプションが付いているので、2分後に自動終了します。 (バッテリー低下時は速攻で、ケーブル異常時は1分後) これで、停電(電源異常)時には、2分後に、システムが自動停止するようになります。 それでは、Linux側の設定に入ります。 まずは、UPSを接続するシリアルポート(COM1)のデバイスを適当な名前をつけて、そいつにリンクします。 わかりやすいように、/dev/UPS とでもしましょう。 ちなみに、VineではCOM1は /dev/ttyS0 、COM2は/dev/ttyS1 となってます。(まぁ、ワシの鯖にはCOM1しか付いてないんで関係ないが)
$ chmod 600 /dev/ttyS0
$ ln -s /dev/ttyS0 /dev/UPS

で、システム起動時にgenpowerd を起動するように /etc/rc.d/rc.local を修正。 $ genpowerd <シリアルポート> <genpowerd.hで追加した設定名> 〜/etc/rc.d/rc.local〜
########################
### start UPS daemon ###
########################
echo "Starting genpowerd Daemon..."
if [ -x /sbin/genpowerd ]; then
   /sbin/genpowerd /dev/UPS omron-bx50ls
fi

そして、停電(電源異常)時に、init の処理を/etc/genpowerfail を起動するようにするため、/etc/inittab を変更。 〜/etc/inittab〜
# When our UPS tells us power has failed, assume we have a few minutes 
# of power left. Schedule a shutdown for 2 minutes from now. 
# This does, of course, assume you have powerd installed and your 
# UPS connected and working correctly. 
# pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down" ←コメントアウト
pf::powerfail:/etc/genpowerfail start ←停電になったらgenpowerfail がstart
# If power was restored before the shutdown kicked in, cancel it.
# pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled" ←コメントアウト
pr:12345:powerokwait:/etc/genpowerfail stop ←シャットダウン前に停電から復帰したら、genpowerfail をstop

最後に、マシンのシャットダウン処理を終了後、UPSの電源を停止するために /etc/rc.d/init.d/halt を修正します。 〜/etc/rc.d/init.d/halt〜
# Now halt or reboot.
echo $"$message"
if [ -f /fastboot ]; then
 echo $"On the next boot fsck will be skipped."
elif [ -f /forcefsck ]; then
 echo $"On the next boot fsck will be forced."
fi

--ココカラ追加--
if [ -r /etc/upsstatus ]; then
   status=`head -1 /etc/upsstatus`
   # Kill power if needed
   if [ $status != "OK" ]; then
      echo "Killing Power..."
      sleep 5
      /sbin/genpowerd -k /dev/UPS omron-bx50ls
   fi
fi
--ココマデ--

HALTARGS="-i -d"
if [ -f /poweroff -o ! -f /halt ]; then
   HALTARGS="$HALTARGS -p"
fi
eval $command $HALTARGS

以上で設定完了♪ これで再起動すれば、genpowerd が立ち上がっているはずです。 $ cat /etc/upsstatus で、OKと表示されたら、genpowerd がちゃんと監視してくれてるぞい。 よーし、この勢いでパパ、テストしちゃうぞぉ〜。 さっそく、シリアルケーブルを繋ぎ、ドキドキしながらUPSの電源ケーブルを引っこ抜きました。 ブチッ!! ・・・。 アレ? 電源落ちたぞ。(汗) いや、仮に設定が失敗してたとしても、暫くはUPSのバッテリーで動くはず。 何故にいきなり電源が落ちる? とりあえず、UPSから電源を取るのを止め、再度Vineserver君の電源をON。 Kernel Panic とは此れ如何に・・・。 いろいろ行いましたが、完全にファイルシステムが壊れてしまったようです。(涙) しかし、先代マシンなんで、既にバックアップ済で痛くも痒くもありません。 仕方ないので、再度Vineをインストールするため、フォーマットにとりかかる。 あっ、フォーマットすらできなくなってんじゃん・・・。 数%フォーマットした段階でフリーズ・・・。 ていうか、しばらくやってると認識すらしなくなってるし。(藁) どうやら、HDDが逝ってしまわれたようです。(号泣) Vineserver君 チーン♪(合掌)
30.4.genpower、それでもオレはオマエが好きだ!!

Vineserverの突然死(いきなりシャットダウン)の原因ですが、

/* OMRON BX50LS */
 {7, "omron-bx50ls",   {TIOCM_RTS,0}, {TIOCM_DTR,0},  5, {TIOCM_CTS,0}, {TIOCM_CAR,0}, {0,0}},

というようにgenpowerd.h 編集時に、DTRの設定を1ではなく0と打ってしまったのではないかと推測しています。 (HDDにアクセスできなくなったんで、本当のところは不明ですが) このVineserverの死亡によって、動作確認は慎重に行わなければならないということを改めて痛感。 新しいLinuxマシンを用意するわけにもいかないので、確認作業は現サーバであるJunkserverで行い、再度失敗しないように注意深く設定しました。 しかし、よくよく考えると、シリアルケーブルを通じ、ちゃんと信号のやり取りが行われて、 電源低下時(停電時)にシャットダウン処理に移行することを確認できればよかったのだから、わざわざUPSに繋ぐメリットはなかったっす。 動作確認 要は、こんな感じで可能だったね、ってこと。 そんなわけで、図のような環境を構築し、PCの電源はUPSを通さないようにして動作確認を行う。 確認事項は以下の通り。  ・UPSの電源ケーブルを抜き、シリアルケーブルを通じてPC側にシャットダウン命令が送られ、   シャットダウンを行う旨のメッセージが表示されるかを確認  ・UPSの電源ケーブルを再度挿して、シリアルケーブルを通じてPC側にシャットダウンキャンセルの命令が送られ、   シャットダウンがキャンセルされるかを確認  ・UPSの電源ケーブルを再度抜き、シリアルケーブルを通じてPC側にシャットダウン命令が送られ、   シャットダウンを行う旨のメッセージが表示された2分後にシャットダウンされるかを確認 一応、UPSのバッテリー低下時の設定も行ったので、本来はそのテストもしたほうがよいのだが、 まだ比較的新しいので、特にする必要はないかな。 (一旦、何らかの形でバッテリーを消費させなきゃいけないので、バッテリーが多少なりともへたってしまうし) というわけで、この3項目について動作確認。(一応、genpowerdが動いていることを確認してから行わないと意味がないですよ〜) 結果はすべてOK。 最初からこうやっておけば、VineserverのHDDが死亡することは無かったわけで…。(汗) これで、雨が降ろうが暴風警報が出ようが電気の使いすぎでブレーカーが落ちようが怖くはありません。 すごいぞgenpower、ボクらのgenpower!! ★あとがき★ このUPSをLinuxで動作させる作業、実は自前のスクリプトを使って去年の正月に行っており、 文章自体も去年の3月ぐらいにはある程度書き終わってたんですよ。 ただ、最後の部分を書こうと思ってから、仕事が急に忙しくなったり、このファイルの存在自体を忘れていたり(爆)、 で、ズルズルと1年以上も経ってしまいました。 この1年もの間、UPSを稼動させて特に問題なかったんだけど、ここ最近、USBポートに何かを挿すとシャットダウンしたりと調子が悪くって。 自前のスクリプトに問題があるのではと思い、他に良いソフトが無いか探していたところ、このgenpowerに出会いました。 まぁ、結果としてはgenpowerでも問題は解決しなかったんですが。(笑) それでも、自前のスクリプトよりは高機能なgenpower、ひさびさにやる気を出して戯言を書いちゃうほど、良いソフトです。

管理人の戯言トップ | ホームに戻る |

webmaster@ashiyu.net