OMRON BW55TでNetwork UPS Toolsを使う
OMRON公式のシャットダウンソフト
- PowerAttendant Standard
- PowerAttendant Lite
- Simple Shutdown Software
- PowerAct Pro
Simple Shutdown SoftwareはオープンソースでC++のコードが提供されていたのだが、PowerAttendant LiteとSimple Shutdown Softwareは2024/3で提供中止になるらしい。
残った公式ツールだが、ドキュメントを確認するとインストール要件が大分辛い。
ネットで検索すると先人たちはNetwork UPS Toolsを使用していることがわかった。
Network UPS Tools(nut)は20世紀からある歴史あるオープンソースプロジェクトでGitHubをみると今も非常にアクティブなよう。元々APCのUPSをサポートするところから始まったようで、今では多くのUPSがサポートされているがOMRONはリストにない。
nutはUPSに直接接続してUPSの状態を配信するサーバプロセスと、サーバに接続してUPSの状態を拾うクライアントプロセスから構成される。このサーバとクライアントの接続プロトコルは2022年にRFCで標準化されている。
標準化されているので色々な言語でこのプロトコルを扱うライブラリがあったり、UPSのメトリクスをPrometheusに送るためのexporterなどがある(これは嬉しい)
nutのインストールはaptで簡単にインストールできる。
# フルインストール
apt install nut
# クライアントのみの場合
apt install nut-client
nutのdriver
設定に対象のUPSに合わせたドライバーを設定するのだが、先人たちの記事を見ると皆driver = blazer_usb
と設定している。
これが何者か調べていると、Ubuntuのマニュアルにて説明が見つかった。
blazer_usb - Driver for Megatec/Q1 protocol USB based UPS equipment
Megatec/Q1 protocolについて調べるとnutsのドキュメントが出てくる。
プロトコルの基本となるUPSからの情報取得はめっちゃシンプルでQ1
+改行と送るとUPSからバッテリーや入力電源の情報が返ってくる仕様。
これ実は、OMRONの公式が出しているオープンソース版のツールであるSimple Shutdown Softwareを見てみると確かにQ1をUPSに送信していることが確認できる。色々繋がってきた。
©OMRON Corporation. 2011 All Rights Reserved.
//*************************************************************************************//
// Parameters:
// szData
// [out] Storage location of data from UPS.
// Return value:
// Return 1, succeed; 0, failed.
// Description:
// Send "Q1" command to UPS, and store the data received from UPS into (szData).
//*************************************************************************************//
int CUPS::UPSCmdQ1(char *szData)
{
UINT i;
for (i = 0; i < MAX_PORT_FAIL_LOOP; i++)
{
if (WritePort("Q1") < 0)
continue;
if (ReadPort(47, szData) > 0)
{
if (strlen(szData) == 47)
return 1;
}
}
ClosePort();
return 0;
}
ここまでわかったのでblazer_usbドライバーを使用して、と思ったがよくよく調べるとうちのNAS(QNAP TS-262)が公式にOmron UPSをサポートしていることを思い出した(そもそもこれを見てOMRONのUPSを買ったんだった)
あたらめて考えるとQNAPのOSであるQTSではOMRON UPSに繋ぐときドライバーは何なの?ということになる。調べてみるとQTSのUPS機能はNetwork UPS Toolsが内部で使われているらしい。
実際にUSBでUPSとQNAPを接続するとすんなり認識され接続ができた。
この状態でQNAP NASにSSH接続して状態を確認してみる。
OS情報
$ cat /etc/*release
NAME="QTS"
VERSION="5.1.2 (20230926)"
ID=qts
PRETTY_NAME="QTS 5.1.2 (20230926)"
VERSION_ID="5.1.2"
$ uname -a
Linux NAS62AD78 5.10.60-qnap #1 SMP Tue Sep 26 01:55:25 CST 2023 x86_64 GNU/Linux
起動中のプロセス
$ ps -ef | grep ups | grep -v grep
2159 admin 1456 S /usr/local/ups/bin/omron_usb -a qnapups -u admin
2222 admin 1484 S /usr/sbin/upsd -u admin
23278 admin 6808 S /usr/sbin/upsutil
まさにNetwork UPS Tools(nut)のserverプロセスであるupsd
とomron_usb
というドライバーが動いていることが確認できた。
nutのクライアントコマンドであるupsc
で確認してみる。
$ upsc -l
qnapups
$ upsc qnapups
battery.charge: 100.0
battery.charge.low: 30
battery.charge.restart: 0
battery.runtime: 3900
battery.temperature: +19.8
battery.voltage: 13.70
battery.voltage.nominal: 024
device.mfr: OMRON
device.model: BW55T
device.serial: XXXXXXXXXX
device.type: ups
driver.name: omron_usb
driver.parameter.pollinterval: 2
driver.parameter.port: /dev/ttyS1
driver.parameter.synchronous: no
driver.version: 2.7.4
driver.version.internal: 1.02
input.frequency: 50.10
input.sensitivity: N
input.voltage: 103.7
input.voltage.fault: 0.0
output.frequency: 50.0
output.voltage: 103.8
output.voltage.nominal: -
ups.beeper.status: enable
ups.delay.reboot: 14
ups.delay.shutdown: 30
ups.delay.start: 180
ups.firmware: 0.32
ups.firmware.aux: 1.04
ups.load: 12.0
ups.mfr: OMRON
ups.model: BW55T
ups.power: 550
ups.productid: 00d0
ups.realpower: 340
ups.serial: XXXXXXXXXX
ups.start.auto: yes
ups.start.battery: no
ups.status: OL
ups.temperature: 25.9
ups.type: offline / line interactive
ups.vendorid: 0590
ちゃんとUPSの情報を取得することができた。
nutの設定ファイルも確認できる。
$ ll /etc/config/ups
total 40K
drwxr-xr-x 2 admin administrators 4.0K 2024-01-09 11:49 ./
drwxr-xr-x 51 admin administrators 12K 2024-01-18 00:00 ../
-rw-r--r-- 1 admin administrators 83 2024-01-09 11:49 ups.conf
-rw-r--r-- 1 admin administrators 1.2K 2024-01-09 11:49 upsd.conf
-rw-r--r-- 1 admin administrators 2.4K 2023-01-14 00:08 upsd.users
-rw-r--r-- 1 admin administrators 12K 2024-01-09 11:49 upsmon.conf
そしてUPSの設定をみると、driver = blazer_usb
ではなくdriver = omron_usb
が設定されていることがわかる。
$ cat ups.conf
[qnapups]
driver = omron_usb
port = /dev/ttyS1
desc = "Workstation"
pollinterval=2
じゃあblazer_usb
はないのかというと、先ほどプロセスを確認した際にomron_usb
が/usr/local/ups/bin
にあったので、そこを見てみるとblazer_usb
もあった。
ll /usr/local/ups/bin
total 1.4M
drwxr-xr-x 2 admin administrators 160 2023-09-26 04:36 ./
drwxr-xr-x 7 admin administrators 140 2023-09-26 04:36 ../
-rwxr-xr-x 1 admin administrators 100K 2023-09-26 04:36 blazer_usb*
-rwxr-xr-x 1 admin administrators 784K 2023-09-26 04:36 nutdrv_qx*
-rwxr-xr-x 1 admin administrators 99K 2023-09-26 04:36 omron_usb*
-rwxr-xr-x 1 admin administrators 88K 2023-09-26 04:36 riello_ser*
-rwxr-xr-x 1 admin administrators 97K 2023-09-26 04:36 riello_usb*
-rwxr-xr-x 1 admin administrators 216K 2023-09-26 04:36 usbhid-ups*
やっと全体像がわかってきた。OMRONは公式でUPSへの接続を行う製品企業のためにUPSのプロトコルを開示している。
個人で申請できるかわからないので開示請求はしていないが、要するにQNAPがこれを実装したドライバーがomron_usb
なのだと思う。
オープンソース版のSimple Shutdown Softwareをみる限りでは、情報取得のためのQ1コマンドとUPS自体(?)をシャットダウンするためのSNコマンドの存在は確認できるが、プロトコル仕様の全量はわからない。
しかしblazer_usb
ではなくちゃんとomron_usb
があるということは、基本的にはMegatec/Q1 protocolをベースとしたものだろうが、恐らく何かしら拡張仕様などがあるものと思われる。
ただ先人たちの記事からUPSの電源喪失時にサーバをシャットダウンするような基本的な使い方であればblazer_usb
でも代替できると思われる。
が、せっかくQNAPのNASを持っているので、QNAP NASにomron_usb
ドライバーを使用したnut serverになってもらい、他のサーバにはQNAP NASをMasterとしたnut-clientを導入しようと思う。これで構成が決まった。
Master側、つまりNASの設定はQNAPだとめちゃめちゃ簡単だ。
USBでQNAP NASとUPSを繋いで、QTSのGUI上で設定を行うだけ。ちょっとややこしいのは
QTS上では「Network UPS Tools」や「upsd」といったNetwork UPS Toolsの専門用語は一切登場しないことだ。
NAS側をMasterにするため他のサーバから接続できるようにする必要がある。
QTSの画面上に「ネットワークUPSサポート」なるものがあるので、これを有効化して仮で立てた仮想マシンのIPを設定してみた。
この状態でSSH接続してnutの設定ファイルがどうなっているか確認してみる。
upsd.conf
が更新され、リスナーが他のサーバからの接続を受け付けられるようにし、ACLで接続元のIPがGUI上で設定したIPのみが許可されていることがわかる。
$ cat upsd.conf
# Network UPS Tools: example upsd configuration file
#
# This file contains access control data, you should keep it secure.
#
# It should only be readable by the user that upsd becomes. See the FAQ.
# =======================================================================
#
#
# REJECT <aclname> [<aclname>...]
#
#
# allowed to connect to upsd.
#
# This default configuration only gives access to localhost. To allow
# other hosts or networks to connect, see the documentation and change
# these lines.
ACL all 0.0.0.0/0
ACL localhost 127.0.0.1/32
ACL client_1 192.168.1.111/32 <----追加された
ACCEPT localhost
ACCEPT client_1
REJECT all
MAXAGE 20
# =======================================================================
# MAXAGE <seconds>
# MAXAGE 15
#
# This defaults to 15 seconds. After a UPS driver has stopped updating
# the data for this many seconds, upsd marks it stale and stops making
# that information available to clients. After all, the only thing worse
# than no data is bad data.
#
# You should only use this if your driver has difficulties keeping
# the data fresh within the normal 15 second interval. Watch the syslog
# for notifications from upsd about staleness.
LISTEN 0.0.0.0 <----追加された
仮で起動した仮想マシンにnut-clientをインストールしてQNAP NASのnut-serverに接続できることを確認する。
$ upsc qnapups@[NASのIPアドレス]
Init SSL without certificate database
battery.charge: 100.0
battery.charge.low: 30
battery.charge.restart: 0
battery.runtime: 3900
battery.temperature: +19.8
battery.voltage: 13.70
battery.voltage.nominal: 024
device.mfr: OMRON
device.model: BW55T
device.serial: XXXXXXXXXX
device.type: ups
driver.name: omron_usb
driver.parameter.pollinterval: 2
driver.parameter.port: /dev/ttyS1
driver.parameter.synchronous: no
driver.version: 2.7.4
driver.version.internal: 1.02
input.frequency: 50.10
input.sensitivity: N
input.voltage: 103.7
input.voltage.fault: 0.0
output.frequency: 50.0
output.voltage: 103.8
output.voltage.nominal: -
ups.beeper.status: enable
ups.delay.reboot: 14
ups.delay.shutdown: 30
ups.delay.start: 180
ups.firmware: 0.32
ups.firmware.aux: 1.04
ups.load: 12.0
ups.mfr: OMRON
ups.model: BW55T
ups.power: 550
ups.productid: 00d0
ups.realpower: 340
ups.serial: XXXXXXXXXX
ups.start.auto: yes
ups.start.battery: no
ups.status: OL
ups.temperature: 25.9
ups.type: offline / line interactive
ups.vendorid: 0590
問題なく接続できた(最初にSSLに起因するメッセージが出たが)
とりあえずクライアントから接続できることは確認できたので、各サーバに導入するnut-clientの設定を試していきたい。
基本的にはUPSの電源喪失を検知したら適当なシャットダウンコマンドができればいい。Proxmoxのホストサーバ等にnut-clientを導入するつもりだが、上で動いているKubernetesクラスターではNASにiscsiで接続しているPodがいたりするため、このあたりはちゃんとPodを止めてシャットダウンしたい。が、ここは後からシャットダウンのスクリプトやプログラムを作ればいいので、とりあえず任意のコマンドが実行できるまで確認していきたい。
nutの設定は結構色々あるのでとりあえず主要な設定例を確認したい。と思ってドキュメントを眺めているとExample Bookというのがあった。
NUT Configuration Examples book maintained by Roger Price
オープンソースのExampleなのだが、Bookと名のつく通りLaTeXで書かれていてリリースがPDFという硬派というか歴史を感じるドキュメントだった。ただ非常によく書かれたドキュメントで大体の設定イメージがわかる。
クライアントプロセスはupsmon
というデーモンプロセスで、これだけを起動する場合nut.conf
のMODEにnetclient
を設定する。
$ cd /etc/nut/
$ cat nut.conf
...
MODE=netclient
次にupsmon.conf
の設定を行う。設定する項目は大体以下のようなものになりそう(デフォルトで入っていたもの含め)
SHUTDOWNCMD "/sbin/shutdown -h +0" # シャットダウンコマンド
NOTIFYCMD /usr/sbin/upssched # 通知コマンド
POLLFREQ 5 # サーバへのpolling間隔秒数
POLLFREQALERT 5 # サーバへのpolling間隔(UPSバッテリー駆動時)
DEADTIME 15 # この秒数UPSの情報が取得できなかった場合、UPS喪失とみなす。
POWERDOWNFLAG /etc/killpower
HOSTSYNC 5 # シャットダウン状況中にセカンダリが切断されるまで、プライマリが待つ秒数
MINSUPPLIES 1 # 複数のUPSを繋いでいる際にUPSの数がこの値を下回ったらシャットダウンを行う
RBWARNTIME 43200 # バッテリー交換アラート送信間隔秒数
NOCOMMWARNTIME 300 # UPS設定が1つもない場合のアラート
FINALDELAY 5 # NOTIFYCMDを実行した後にSHUTDOWNCMDを実行するまでの待機秒数
細かな設定は置いておいて、まず自分のためにカスタマイズする部分としては、SHUTDOWNCMD
とNOTIFYCMD
のようだ。今回は何かイベントがあればDiscordに通知するようにしたい。上記のupsmonの設定に入れるのかと思ったが、いくつかの例を見るとNOTIFYCMD
は上記のようにupssched
を設定することが一般的なようだ。
upsschedのマニュアルをみるとupsmonとは別プログラムとしてupsschedを作った背景などが書かれている。upsmonの設定上はNOTIFYCMDを1つ指定するだけになっているが、いくつかイベントの種類があるため、イベントの種類に応じたプログラムを実行できるようにしたみたい。イベントを区別する必要がない人はこの機能がいらないためとあるがその他の機能もあるため、いくつか先人のサイトをみる限り基本的にこれを使っている模様。