UPSとApcupsdを用いて停電時にサーバーを自動で停止させる

計画停電の前にわざわざ研究室に来て、サーバーを手動で落とす生活には耐えられない。なので、自動停止環境を整えることにする。

Debian GNU/Linux testing

まずは念のためパッケージ更新。

% sudo aptitude update
% sudo aptitude safe-upgrade

USBを認識させるためにkernelを再構築する必要がある。

% sudo aptitude instlal linux-source-2.6.32

Linux kernel 2.6.xの場合以下のモジュールを組み込まないといけない。2.6.32.xで make menuconfigしたときの対応は以下のとおり。(
なお、HELPでどのフラグがONになるのかを調べることができる)

  • CONFIG_USB : Device Drivers → USB Support → Support for Host side USB
  • CONFIG_USB_HID: Device Drivers → HID Support → USB Human Interface Device (full HID) suport
  • CONFIG_USB_HIDDEV: Device Drivers → HID Support → /dev/hiddev raw HID device support
  • CONFIG_USB_DEVICEFS : Device Drivers → USB Support → USB device filesystem
  • CONFIG_USB_UHCI_HCD (linux-2.6.x): Device Drivers → USB Support → UHCI HCD support
  • CONFIG_USB_OHCI_HCD (linux-2.6.x): Device Drivers → USB Support → OHCI HCD support
% cd /usr/src
% rm linux (前にカーネルの再構築をしたことがある場合のみ)
% tar xvfj linux-source-2.6.32.tar.bz2
% ln -s linux-source-2.6.32 linux
% cd linux
% cp ../linux-source-2.6.x/.config ./ (前にカーネルの再構築をしたことがある場合のみ)
% make menuconfig

grepなどで上のフラグが設定されていることを確認する。たとえば以下のように。

% grep USB .config | grep HID 

ちゃんと設定したならば、イメージファイルを生成。

% make-kpkg --revision=YYYYMMDD kernel-image kernel-header
% cd ..
% sudo dpkg -i linux-image-2.6.32_YYYYMMDDD_i386.deb
% sudo dpkg -i linux-headers-2.6.32_YYYYMMDD_i386.deb

UPSとサーバーをUSBケーブルでつなぐ。そして、サーバーを再起動させる。もし、サーバーの再起動時に電源スイッチを物理的に押さなければならない人は、BIOSから設定を変えること。Dellの場合は以下のとおり。

% sudo reboot

再起動したら、ちゃんと新しいカーネルで動いているかを確認。

% uname -a
Linux *** 2.6.32 #2 SMP Fri Mar 18 18:57:29 JST 2011 i686 GNU/Linux

次にUPSを認識できているかをチェックする。

% dmesg | grep usb
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
usb usb1: configuration #1 chosen from 1 choice
usb usb2: configuration #1 chosen from 1 choice
usb usb3: configuration #1 chosen from 1 choice
usbcore: registered new interface driver hiddev
usbcore: registered new interface driver usbhid
usbhid: v2.6:USB HID core driver
usb 2-1: new full speed USB device using uhci_hcd and address 2
usb 2-1: configuration #1 chosen from 1 choice
usb 3-2: new low speed USB device using uhci_hcd and address 2
usb 3-2: configuration #1 chosen from 1 choice
generic-usb 0003:051D:0002.0001: hiddev96: USB HID v1.10 Device [American Power Conversion Smart-UPS 1500 RM DLJ2 FW:617.1DLJ2.A USB FW:1.5] on usb-0000:00:1d.2-2/input0
usb 2-1.2: new full speed USB device using uhci_hcd and address 3
usb 2-1.2: configuration #1 chosen from 1 choice
usb 2-1.2.1: new full speed USB device using uhci_hcd and address 4
usb 2-1.2.1: configuration #1 chosen from 1 choice
generic-usb 0003:04FE:0006.0002: input: USB HID v1.00 Keyboard [Chicony PFU-65 USB Keyboard] on usb-0000:00:1d.1-1.2.1/input0

「generic-usb 0003:051D:0002.0001: hiddev96: USB HID v1.10 Device [American Power Conversion Smart-UPS 1500 RM DLJ2 FW:617.1DLJ2.A USB FW:1.5] on usb-0000:00:1d.2-2/input0」とUPSが認識されている。

apcupsdをインストール

% sudo aptitude install apcupsd apcupsd-doc

Debianの場合は、/usr/share/doc/apcupsd/examplesにあるmake-hiddevを実行する。

% sudo /usr/share/doc/apcupsd/examples/make-hiddev

次に設定ファイルを編集する。

% cd /etc/apcupsd
% sudo cp -p apcupsd.conf apcupsd.conf.org
% sudo vi apcupsd.conf

重要な変更点は以下のとおり。

  • UPSCABLE smart → UPSCABLE usb
  • UPSTYPE apcsmart → UPSTYPE usb
  • DEVICE /dev/ttyS0 → DEVICE /dev/usb/hid/hiddev0


以上の項目について変更したのちに、/etc/default/apcupsdのISCONFIGURED=noをISCONFIGURED=yesに書き換える。

% sudo vi /etc/default/apcupsd

apcupsdを立ち上げる。

% sudo /etc/init.d/apcupsd start

UPSの情報をチェック。

% apcaccess

うまくUPSの情報をとれない場合は /var/log/apcupsd.eventsを参照のこと。

% tail /var/log/apcupsd.events

apcupsd.confの設定については、以下のエントリーが参考になる。

TIMEOUTを30秒に設定してUPSのコンセントを抜いてみたところちゃんとshutdownした。

ネットワーク経由で複数のサーバーをshutdownさせる

構成は以下のとおり。

  1. UPS1 (Smart UPS 1500 RM)
  2. UPS2 (Smart UPS 1000)
    • SUN Blade 1000, Solaris 10: スレイブ
    • スイッチングHub

上記3台のサーバーは、UPS2につないでいるスイッチングHubにてLANで接続されている。

マスターの設定

マスターはUPSと直接つながっているサーバーのこと。今回は、上で接続したDebian GNU/Linux testingのサーバー。ITmedia エンタープライズ:How-To:特別企画:UPSを利用した電源対策を参考に設定した。ただし、上記記事は情報が多少古いみたい。

/etc/apcupsd.confの以下の項目をネットワーク用に変更する。

  • NETSERVER on
  • NISPORT 3551 (必要に応じて適当なポート番号に変える)

Debian GNU/Linux のapcupsdは標準でtcp_wrapperによるアクセス制限を行っている。そこで、/etc/hosts.allowに以下を追加する。

apcupsd: スレーブサーバー1のIPアドレス スレーブサーバー2のIPアドレス LOCAL

以上を設定したら、apcupsdを立ち上げ直す。

% sudo /etc/init.d/apcupsd restart

スレイブサーバーの設定

今回は、Solaris 9とSolaris 10。どちらもインストールの仕方は同じ。Apcupsd a daemon for controlling APC UPSesからソースコードをダウンロードしてきてインストールする。なお、/usr/ucbをコマンドパスにいれていると、make後にそれをはずすように推奨される。

% gtar xvfz apcupsd-3.14.8.tar.gz
% cd apcupsd-3.14.8
% ./configure --with-libwrap=/usr/local/lib |& tee configure.log
% gmake |& tee make.log
% sudo gmake install

インストールが終わると/etc/opt/apcupsd 設定ファイルとsbinが保管され、起動スクリプトが/etc/init.d/apcupsd にまた、/etc/rc2.d/S89apcupsd としてリンクがはられる(すなわち、再起動したら自動的にapcupsdが起動する)。

/etc/opt/apcupsd/apcupsd.confは以下のように設定する。

  • UPSCABLE ether
  • UPSTYPE net
  • DEVICE マスターのIPアドレス:3551
  • POLLTIME 60(マスターに問い合わせにいく間隔:秒)
  • EVENTSFILE /var/log/apcupsd.events (ログの出力先。デフォルトは/etc/opt/apcupsd/apcupsd.events)

また、/etc/hosts.allowに以下の設定を加える。

apcupsd: LOCAL

その後、apcupsdを立ち上げる。

% sudo /etc/init.d/apcupsd start

しばらくして、/etc/opt/apcupsd/sbin/apcaccess コマンドでマスターと同じUPSの情報がでたならば、設定成功。

あとは、UPSのバッテリー容量とマスターとスレイブの停止タイミングを勘案して、BATTERYLEVEL(バッテリー容量が残りX%になったら停止)、MINUTES(バッテリー持続時間が残りX分になったら停止)、TIMEOUT(バッテリー運転になってX秒後に停止)を適切に設定すればよい。

おまけ:SolairsをUSB経由でUPSにつなぐ(ダメだった)

シリアルケーブルが見当たらないので、USB経由で行おうとしたら

  • Solaris 9は対象外(USBを使うためのドライバはもう公式では配布していない)
  • Solaris 10は対象なのだけど、うまく行かない。Sun Blade 1000にSmart UPS 1000をUSB

接続してやってみているのだけど、/etc/init.d/apcupsd start を実行すると次のメッセージがでてしまう。

% dmesg 
〜 省略 〜
Mar 16 18:51:40 *** apcupsd[662]: [ID 702911 daemon.error] Valid lock file for pid=378, but not ours pid=662
Mar 16 18:51:41 *** apcupsd[663]: [ID 702911 daemon.error] apcupsd FATAL ERROR in generic-usb.c at line 636
Mar 16 18:51:41 *** Cannot find UPS device --
Mar 16 18:51:41 *** For a link to detailed USB trouble shooting information,
Mar 16 18:51:41 *** please see <http://www.apcupsd.com/support.html>.
Mar 16 18:51:41 *** apcupsd[663]: [ID 702911 daemon.error] Valid lock file for pid=378, but not ours pid=663
Mar 16 18:51:41 *** apcupsd[663]: [ID 702911 daemon.error] apcupsd error shutdown completed

APCUPSDマニュアル:Verifying Device Detection and Driver

fter installing Apcupsd as described above and performing a reconfigure boot, plug in your UPS USB cable. You should see a series of dmesg log messages similar to the following:

Dec  5 17:50:50 sunblade usba: [ID 912658 kern.info] USB 1.10 device (usb51d,2) operating at low speed (USB 1.x) on USB 1.10 root hub: input@4, ugen0 at bus address 3
Dec  5 17:50:50 sunblade usba: [ID 349649 kern.info]    American Power Conversion Smart-UPS 1000 FW:600.1.D USB FW:1.2 AS0127232356
Dec  5 17:50:50 sunblade genunix: [ID 936769 kern.info] ugen0 is /pci@1f,0/usb@c,3/input@4
Dec  5 17:50:50 sunblade genunix: [ID 408114 kern.info] /pci@1f,0/usb@c,3/input@4 (ugen0) online

Note that the ugen driver is called out. If you do not see any dmesg entries related to your UPS, ensure that it is turned on and that the USB cable is connected at both ends. Also verify that you installed Apcupsd as root using the 'make install' command and that you performed a reconfigure boot afterward.

となっているので、チェックしたら、同じようになっている。

Mar 16 17:54:20 ** pcisch: [ID 370704 kern.info] PCI-device: usb@5,3, ohci0
Mar 16 17:54:20 ** genunix: [ID 936769 kern.info] ohci0 is /pci@8,700000/usb@5,3
Mar 16 17:54:21 ** usba: [ID 912658 kern.info] USB 1.10 device (usb51d,2) operating at low speed (USB 1.x) on USB 1.10 root hub: input@2, ugen0 at bus address 2
Mar 16 17:54:21 ** usba: [ID 349649 kern.info]   American Power Conversion Smart-UPS 1500 FW:601.3.A USB FW:1.5 AS0237111879
Mar 16 17:54:21 ** genunix: [ID 936769 kern.info] ugen0 is /pci@8,700000/usb@5,3/input@2
Mar 16 17:54:21 ** genunix: [ID 408114 kern.info] /pci@8,700000/usb@5,3/input@2 (ugen0) online

デバイスもDevice Nodesと同じなのに。

[user@sunblade /]$ ls /dev/usb/51d.2/*
cntrl0      cntrl0stat  devstat     if0in1      if0in1stat

何がわるいんだろう?がんばって、シリアルポート用のケーブル探すか。上述のように、ネットワーク経由でどうにかした。