Автор Тема: Настройка NUT для управления ИБП.  (Прочитано 33659 раз)

Оффлайн freddyb

  • Начинающий
  • *
  • Сообщений: 40
Делюсь решением. Можно заменить сильно устаревший wiki: https://www.altlinux.org/NUT

Дано: ПК с ОС AltLinux 7.0.5 Centaurus x64. Этот ПК запитан от ИБП с USB-интерфейсом (с СОМ-интерфейсом тоже будет работать). Задача: через заданное время после пропадания сетевого питания выгрузить ОС и выключить ИБП. Штатная утилита для управления ИБП от производителя UPSMON Pro (использует java-x32) не работает на х64 ОС. Поэтому для управления ИБП будем использовать пакет NUT.

В AltLinux 7.0.5 есть пакеты nut и nut-server.
Пакет nut - это клиентская часть NUT (в других дистрибутивах может быть не так: в RHEL это сервер NUT, и тогда есть ещё пакет nut-client. В Ubuntu сервер и клиент находятся в одном пакете nut). Пакет nut-server - это серверная часть nut.
Ставим оба пакета: nut и nut-server. А вообще NUT состоит из 3-х уровней: сервер, драйвер и клиент.
apt-get install nut
apt-get install nut-server
Появились службы upsd и upsmon.
Cлужба upsd (сервер) сама работает от имени пользователя upsd, запускает драйвер нужного ИБП от имени пользователя upsdrv и принимает соединения по сети от служб-клиентов upsmon. Сама служба upsd не инициирует сетевых соединений.
Служба upsmon (клиент) работает в двух экземплярах: от имени пользователей upsmon и root. upsmon через upsd взаимодействует с ИБП. Служба upsmon должна быть на ПК, запитываемых от ИБП. Когда один ИБП питает несколько ПК, то один из ПК (который интерфейсным кабелем подключён к ИБП) имеет upsmon в режиме master, а остальные ПК имеют upsmon в режиме slave. Служба upsmon slave подключается по сети к службе upsd запущенной на ПК со службой upsmon master.
Настройки лежат в /var/lib/nut/etc/nut/ и в /etc/nut/.

Сначала проверим, видит ли наша ОС наш ИБП с USB-интерфейсом:
lsusb
Если в ответе есть строка с нашим ИБП, то идём далее.

Настроим конфигурационные файлы:

/etc/nut/nut.conf - в этом файле указано, какие компоненты nut надо запускать. Для случая один ПК - один ИБП внесём:
MODE=standalone

ups.conf - в этом файле настройки всех ИБП, контролируемых сервером. Файл ups.conf существует в двух экземплярах: /etc/nut/ups.conf и /var/lib/nut/etc/nut/ups.conf. Редактируем /etc/nut/ups.conf, а затем система сама переносит его содержимое в /var/lib/nut/etc/nut/ups.conf.
Внесём свои настройки для ИБП Powercom SMK-2500A-RM-LCD:
[smk2500a1]
    port = auto
    driver = usbhid-ups
    desc = "Powercom SMK-2500A-RM-LCD-1"

- [smk2500a1] - произвольное название ИБП
- Название driver берётся из списка http://networkupstools.org/stable-hcl.html для нужной модели ИБП.
- Название port для USB-подключения (с любым USB-драйвером) обычно auto, и только если есть несколько ИБП с USB, то возможно придётся ставить другие значения port. См. описание опций соответствующего драйвера USB. Например, описание опций драйвера usbhid-ups:  http://networkupstools.org/docs/man/usbhid-ups.html

В этом файле можно указать ещё два полезных параметра offdelay и ondelay (в данном конкретном случае мы их не указываем, а оставляем по умолчанию). Эти параметры могут работать по разному для разных драйверов (смотри их man-ы http://networkupstools.org/docs/man/). В частности, у разных драйверов эти параметры могут измеряться в минутах или секундах.  Эти параметры работают так: offdelay = х говорит, что после пропадания питания, выгрузки ОС и посыла команды выключить питание самому ИБП, ИБП будет ждать х сек. а только потом ИБП выключится. Это наверно необходимо, когда некоторые slave-клиенты долго выключаются и для них нужно сделать эту задержку. Если сетевое питание восстановится во время процесса выключения, то ИБП все-равно должен сначала выключиться, а потом опять включиться. ondelay = у говорит, что после того, как будет послана команда выключить питание самому ИБП, он должен опять включиться через у сек., при условии, конечно, что сетевое питание восстановилось. Очевидно, что offdelay должно быть всегда меньше, чем ondelay, иначе ИБП вообще не выключится и ОС не загрузится.
Сообщается, что некоторые ИБП могут включиться после ondelay, даже если нет сетевого питания. Для таких ИБП надо ставить ondelay = -1.

Для проверки правильности настроек ups.conf, надо запустить драйвер:
upsdrvctl start
Если будет выдана ошибка, то надо проверить правильность указания драйвера, возможно нужно указать дополнительные настройки драйвера (см. описание конкретного драйвера).
В нашем случае видим ошибку:
Can't chdir to /var/lib/upsd: Permission denied
Это значит, что в одном из каталогов, находящихся по пути к upsd не разрешен поиск.
/var/lib/upsd это ссылка на /var/lib/nut/var/lib/upsd. Даём всем каталогам по пути к upsd (это каталоги nut, var, lib, и сам upsd) право "х" для всех, и эта ошибка пропадает.
Перезагружаем ПК. Драйвера при загрузке ОС не загрузились и выдали ошибку. Стартуем вручную драйвера и видим эту ошибку:
upsdrvctl start
No matching HID UPS found
т.е. NUT не видит ИБП. Ничего, оставляем ошибку на потом.

Запускаем upsd и видим ошибки:
upsd
fopen /var/lib/upsd/upsd.pid: No such file or directory
файл upsd.pid появляется после запуска upsd и пропадает после его остановки (upsd -c stop), так что ошибка не опасная.
Ещё 2 ошибки:
/etc/nut/cmdvartab not found - disabling descriptions
Can't open /etc/nut/upsd.users: Permission denied
Даем ко всем файлам в /var/lib/nut/etc/nut/ право r всем (644) для всех файлов, кроме upsd.conf (640), и эти две ошибки пропадают. Зато теперь запуск upsd говорит: /etc/nut/upsd.users is world readable, но тут уж ничего не поделаешь.
Даём к /var/lib/nut/var/lib/upsd/ доступ 777 (если оставим 770, то будут ошибки) и перезагрузим ПК. Обе службы (UPS drivers и UPS information service) запустились без ошибок.
Теперь делаем upsdrvctl stop и upsdrvctl start запускается без ошибки:
Network UPS Tools - UPS driver controller 2.6.5
Network UPS Tools - Generic HID driver 0.37 (2.6.5)
USB communication driver 0.31
Using subdriver: PowerCOM HID 0.3

Переходим к следующему конфигурационному файлу:
/var/lib/nut/etc/nut/upsd.conf - в этом файле указывается, откуда сервер upsd принимает сетевые соединения. Если ничего не указывать, то принимает с 127.0.0.1. Для нас подходит. В ранних версиях NUT были директивы ACL, ACCEPT и REJECT. Теперь их нет.

В NUT есть интересные команды работы с ИБП, проверим их работу:
upsc - команда показывает состояние ИБП: напряжения, температура и т.д.
upsrw - просмотр и изменение переменных внутри ИБП, например интервала между самотестированием и т.д.
upscmd - отправить команду на ИБП: запустить тестирование, калибровку и т.д.

Проверим данные от ИБП:
upsc smk2500a1
Данные даёт правильно.
Обращаем внимание на показатель ups.status: OL - On Line, OB - On Battery, LB - Low Battery.

Проверим, какие команды принимает ИБП:
upscmd -l smk2500a1
Instant commands supported on UPS [smk2500a1]:
beeper.toggle - Toggle the UPS beeper
load.on - Turn on the load immediately
load.on.delay - Turn on the load with a delay (seconds)
shutdown.return - Turn off the load and return when power is back
shutdown.stayoff - Turn off the load and remain off
test.battery.start.quick - Start a quick battery test

Проверим, какие переменные внутри ИБП можно менять:
upsrw smk2500a1
[ups.delay.shutdown]
Interval to wait after shutdown with delay command (seconds)
Type: STRING
Value: 20
[ups.delay.start]
Interval to wait before (re)starting the load (seconds)
Type: STRING
Value: 60

Следующий конфигурационный файл:
/var/lib/nut/etc/nut/upsd.users - пользователи имеющие доступ к службе upsd. По умолчанию пустой. Права к нему 644, хотя это и не правильно, но с правами 640 не работает. Создаём пользователей в upsd (не в ОС, а в программе NUT): пользователь monuser для подключения upsmon master-а к upsd и пользователь admin для подключения к upsd вручную. Этот admin нужен, чтобы программой upsrw вручную менять переменные внутри ИБП, если это нам понадобится. Итак, в файле upsd.users пропишем:
[admin]
        password = mypass
        actions = set
        actions = fsd
        instcmds = all

[monuser]
        password = mypass
        upsmon master

Перезагрузим ОС и сделаем дальнейшие настройки:

/etc/nut/upsmon.conf - основные настройки работы с ИБП:
главная директива, говорящая, за каким ИБП наблюдать, имеет такой синтаксис:
MONITOR ИБП@ПК 1 имя пароль master|slave
где ПК - ПК со службой upsd, к которой подключается upsmon. ИБП - название ИБП, которое в квадратных скобках в файле ups.conf. Имя и пароль из файла upsd.users
в нашем случае ставим MONITOR smk2500a1@localhost 1 monuser mypass master
POLLFREQ 5 - частота проверки upsmon-ом работоспособности ИБП в сек.
POLLFREQALERT 5 - то же, но в режиме On Battery.
HOSTSYNC 15 - этот параметр у upsmon master-а означает: столько времени upsmon master оставляет slave-ам выключиться (когда сетевое питание пропало и подана команда на выгрузку ОС); этот параметр у upsmon slave-а означает: если upsmon slave узнал о статусе Low Battery, то он столько времени ждёт от upsmon master-а команды на выключение (команда называется FSD - forced shutdown). Если это время прошло, то upsmon slave считает, что upsmon master сломался, и не ожидая от него команды, отключается самостоятельно.
DEADTIME - показывает через какое время ИБП будет отмечен как "мёртвый" при потере с ним связи. Надо ставить в 3 раза больше чем наибольшее из POLLFREQ и POLLFREQALERT.
FINALDELAY 5 - сколько сек. подождать перед запуском завершения работы.
NOTIFYFLAG - действия upsmon-a при наступлении некого события. По умолчанию (когда все NOTIFYFLAG закомментированы), работают только  действия SYSLOG и WALL: т.е. при всех возможных событиях upsmon делает запись в системный лог и отправляет сообщение залигинившемся пользователям. Т.е. при переходе на батареи или возвращении на сетевое питание сообщения об этом будут приходить, ничего дополнительно делать не надо. Можно ещё указать запускать скрипт словом EXEC, а сам скрипт указать в NOTIFYCMD. Например:
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYCMD - скрипт для запуска, один для всех событий. Скрипт нужно написать самостоятельно, но мы этого делать не будем. В качестве скрипта будем использовать имеющийся в пакете NUT планировщик upssched:
NOTIFYCMD /usr/sbin/upssched

По умолчанию NUT может запускать завершение работы ОС только при наступлении события LB (Low Battery), т.е когда батареи почти разрядились. Но нам это не подходит, мы хотим запускать завершение работы ОС через определённое время после пропадания сетевого питания. Рассмотрим, что вообще происходит в программе NUT при пропадании питания:
- В ИБП разряжаются батареи и ИБП сообщает upsmon master-у свой статус: ups.status: OB LB.
- upsmon master видит этот статус  и ставит флаг FSD (forced shutdown).
- upsmon slave-ы видят этот флаг FSD и генерируют событие NOTIFY_SHUTDOWN, ждут FINALDELAY секунд, запускают скрипт SHUTDOWNCMD (указан в upsmon.conf, обычно /sbin/shutdown -h +0) и отключаются от upsd.
- upsmon master после выставления FSD ждёт HOSTSYNC секунд пока upsmon slave-ы отключатся от upsd.
- upsmon master генерирует событие NOTIFY_SHUTDOWN, ждёт FINALDELAY секунд, создаёт файл POWERDOWNFLAG (указан в upsmon.conf, обычно /etc/killpower) и запускает скрипт SHUTDOWNCMD.
- init выгружает всё что положено, находит файл POWERDOWNFLAG и сообщает драйверу ИБП выключить питание.

Нам это не подходит, мы хотим запускать завершение работы ОС через определённое время после появления статуса OB (On Battery), т.е. перехода на батареи. Для этого нужны дальнейшие настройки.
В upsmon.conf ставим:
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYCMD /usr/sbin/upssched
т.е. при событиях: переход на батареи или возвращение на питание от сети, upsmon запускает планировщик upssched.
Событие Low Battery будет отрабатываться правильно и так, без дальнейших настроек.

Далее настроим планировщик в файле /etc/nut/upssched.conf:
CMDSCRIPT /usr/bin/upssched-cmd - планировщик будет запускать этот скрипт upssched-cmd при команде от таймеров. Заполнением скрипта займёмся потом.
PIPEFN /var/lib/upsd/upssched/upssched.pipe
LOCKFN /var/lib/upsd/upssched/upssched.lock
Это два служебных файла. Для них создадим папку /var/lib/nut/var/lib/upsd/upssched/ с владельцем и группой upsmon и правами 775.
AT ONBATT * START-TIMER shutdown-timer 120 - директива говорит, что при наступлении события ONBATT на любом (*) ИБП, запускается таймер с названием shutdown-timer. Через 120 сек. таймер shutdown-timer сработает, запустит скрипт upssched-cmd и передаст как аргумент скрипту upssched-cmd текст "shutdown-timer".
AT ONLINE * CANCEL-TIMER shutdown-timer - если питание восстановилось до того, как, предыдущий таймер сработал, то таймер shutdown-timer сразу сбрасывается.

Теперь настроим скрипт /usr/bin/upssched-cmd. В нём используются bash-оператор case (который используется, если необходимо сравнивать какую то одну переменную с большим количеством параметров), образец есть в скрипте. Внесём:
case $1 in
     shutdown-timer)
          logger -t upssched-cmd "Shutdown timer reached, calling upsmon -c fsd."
          /usr/sbin/upsmon -c fsd
          ;;
     *)
          logger -t upssched-cmd "Unrecognized command: $1"
          ;;
esac

Как это работает: через 120 сек работы от батарей, таймер shutdown-timer передаст скрипту upssched-cmd аргумент "shutdown-timer", скрипт upssched-cmd сообщит в системный лог о выключении и выполнит команду завершения работы upsmon -c fsd. Если скрипту upssched-cmd будет передано любое другое значение, в системный лог будет отправлено об этом сообщение.

Кстати, во время настроек иногда что-то не срабатывает, и тогда полезно бывает остановить NUT и запустить снова:
Порядок остановки вручную:
upsd -c stop
upsdrvctl stop
upsmon -c stop

Порядок запуска вручную:
upsdrvctl start
upsd
upsmon

Проводим эксперимент, всё ли правильно отрабатывает: выдёргиваем вилку из розетки, через 120 секунд ОС начинает выгружаться и ИБП выключается примерно через 20 сек. после выгрузки ОС (т.к. в драйвере usbhid-ups параметр offdelay по умолчанию равен 20 сек.). Вставляем вилку в розетку, ИБП включается и подаёт напряжение на нагрузку.
Проводим другой эксперимент: выдёргиваем вилку из розетки, когда ОС начинает выгружаться, вставляем вилку в розетку. ОС окончательно выгружается, ИБП выключается, примерно через 30 сек. после выгрузки ОС (т.к. в драйвере usbhid-ups параметр ondelay по умолчанию равен 30 сек.) ИБП включается и запитывает нагрузку. Всё верно.