Как правильно готовить apcupsd под FreeBSD
May. 1st, 2019 01:04 pmАлгоритм взаимодействия apcupsd с системой при её выключении не менялся уже 17 лет. По умолчанию apcupsd запускается с ключом --kill-on-powerfail, что означает: при исчерпании заряда аккумулятора в ИБП, послать ИБП команду "уснуть" и одновременно запустить процедуру doshutdown из /usr/local/etc/apcupsd/apccontrol. В ИБП обычно предусмотрена задержка (так называемый grace delay) 10-40 секунд исполнения команд "выключиться" и "уснуть". В этом месте начинается race: что случится раньше, shutdown успеет корректно завершиться или ИБП выключится?
В прежние времена, наверное, это всех устраивало, потому что выключение системы проходило быстро и shutdown успевал всё завершить до выключения питания. Хотя напомню, что значение по умолчанию rcshutdown_timeout="90" заведомо больше grace delay любого ИБП. Так что race condition никуда не девался на самом деле.
В нынешнее время с распространением виртуальных машин во время выключения хоста включено время выключения виртуалок, которое может быть весьма значительным. Я например устаналиваю rcshutdown_timeout="240" и kern.init_shutdown_timeout="300"и то виндовые VM выключиться не успевают. Понятно, что в UPS grace delay не укладываемся точно.
Поэтому предлагаю новый алгоритм выключения системы посредством apcupsd, и открыл на эту тему ПР https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=237600 Суть нового (не очень нового, на самом деле, в Linux используется подобный) алгоритма:
Запускаем apcupsd с ключом --term-on-powerfail
это значит после запуска процедуры shutdown и создания флага /var/run/powerfail apcupsd должен выйти и не путаться пока под ногами.
А в конце /etc/rc.shutdown вписываем строчку
(кому как удобнее, в зависимости от требуемого поведения ИБП после восстановления питания).
Это означает, что только после отработки всех rc.d скриптов с параметром stop в ИБП будет послана команда "уснуть" или "выключиться" соответственно.
UPD A brief summary in English.
My final conclusion. The default way apcupsd is started by the port (with --kill-on-powerfail) is wrong. You cannot rely on the UPS grace shutdown delay even with the default setting of rcshutdown_timeout="90", while using virtual machines necessitates making rcshutdown_timeout even longer. A race between the UPS grace delay and the FreeBSD shutdown procedure must be eradicated.
The only feasible way of doing it is:
1. Starting apcupsd with apcupsd_flags="--term-on-powerfail" so that the daemon exits once it has started the doshutdown procedure and does not send any commands to the UPS at this stage.
2. Putting the line
(depending on the desired behaviour of the UPS after the mains is restored) at the very end of the /etc/rc.shutdown script, after the "Insert other shutdown procedures here" line.
Thus the shutdown procedure started by "apcupsd --term-on-powerfail" can proceed at its own tempo, with "apcupsd --hibernate" being called when all the daemons and VMs have been safely shut down.
UPD 2. Ещё предлагают такой способ: http://www.wfido.ru/m/RU.UNIX.BSD/grosbein.net+c3b53b4f который призван исключить достаточно маловероятную, но неприятную ситуацию, если питание успело восстановиться после завершения apcupsd, но до killpower.
В прежние времена, наверное, это всех устраивало, потому что выключение системы проходило быстро и shutdown успевал всё завершить до выключения питания. Хотя напомню, что значение по умолчанию rcshutdown_timeout="90" заведомо больше grace delay любого ИБП. Так что race condition никуда не девался на самом деле.
В нынешнее время с распространением виртуальных машин во время выключения хоста включено время выключения виртуалок, которое может быть весьма значительным. Я например устаналиваю rcshutdown_timeout="240" и kern.init_shutdown_timeout="300"
Поэтому предлагаю новый алгоритм выключения системы посредством apcupsd, и открыл на эту тему ПР https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=237600 Суть нового (не очень нового, на самом деле, в Linux используется подобный) алгоритма:
Запускаем apcupsd с ключом --term-on-powerfail
apcupsd_enable="YES" apcupsd_flags="--term-on-powerfail"
это значит после запуска процедуры shutdown и создания флага /var/run/powerfail apcupsd должен выйти и не путаться пока под ногами.
А в конце /etc/rc.shutdown вписываем строчку
test -f /var/run/powerfail && /usr/local/sbin/apcupsd --hibernateили
test -f /var/run/powerfail && /usr/local/sbin/apcupsd --power-off
(кому как удобнее, в зависимости от требуемого поведения ИБП после восстановления питания).
Это означает, что только после отработки всех rc.d скриптов с параметром stop в ИБП будет послана команда "уснуть" или "выключиться" соответственно.
UPD A brief summary in English.
My final conclusion. The default way apcupsd is started by the port (with --kill-on-powerfail) is wrong. You cannot rely on the UPS grace shutdown delay even with the default setting of rcshutdown_timeout="90", while using virtual machines necessitates making rcshutdown_timeout even longer. A race between the UPS grace delay and the FreeBSD shutdown procedure must be eradicated.
The only feasible way of doing it is:
1. Starting apcupsd with apcupsd_flags="--term-on-powerfail" so that the daemon exits once it has started the doshutdown procedure and does not send any commands to the UPS at this stage.
2. Putting the line
"test -f /var/run/powerfail && /usr/local/sbin/apcupsd --hibernate"or
"test -f /var/run/powerfail && /usr/local/sbin/apcupsd --power-off"
(depending on the desired behaviour of the UPS after the mains is restored) at the very end of the /etc/rc.shutdown script, after the "Insert other shutdown procedures here" line.
Thus the shutdown procedure started by "apcupsd --term-on-powerfail" can proceed at its own tempo, with "apcupsd --hibernate" being called when all the daemons and VMs have been safely shut down.
UPD 2. Ещё предлагают такой способ: http://www.wfido.ru/m/RU.UNIX.BSD/grosbein.net+c3b53b4f который призван исключить достаточно маловероятную, но неприятную ситуацию, если питание успело восстановиться после завершения apcupsd, но до killpower.