Установка NUT на Xenserver 5.6 SP2

Новости раздела "Грабли". Здесь можно задать вопрос авторам статей.

Установка NUT на Xenserver 5.6 SP2

Сообщение Сергей Дубров » 22 июл 2011, 22:03

Музалёв Николай писал(а):Сергей! Ну что вы спрашиваете? Конечно интересно...
Может и не в чисто практическом плане (по причине других железок), но всегда интересно читать про ваши достижения.
А кроме того - возможны попутные идеи, на которые вы, может, и не акцентируете...

Поскольку проблем встретилось на удивление много, надо их преодоление запротоколировать, для будущих поколений :).

Первая же обнаруженная ссылка по теме (Установка NUT под Citrix XenServer 5.6 SP2 - написано, кстати, весьма толково) оказалась не совсем подходящей к моей ситуации - в ней описывалась установка из подключаемого "на лету" репозитория. И NUT в этом репозитории оказался староват - плохо работал с USB, и вообще не знал моей модели UPS-а (Powercom WOW-500U). Попытки установить NUT из репозиториев посвежее натыкались на обычные проблемы с зависимостями.

Естественный вариант - установить из исходников, но XenServer в этом смысле - недосистема, и на нём нет предустановленного компилятора. Хотел поразбираться с кросс-компиляцией, но решил не усложнять себе жизнь и просто установить недостающие gcc и make прямо на целевую систему.

Т.к. UPS у меня подключается по USB, то, естественно без утилиты lsusb было не обойтись. Но и её "экономные" строители дистрибутива из Citrix-а не приложили. Итак, первая установка (все "лишние" репозитории, по методике из ссылки выше, задизэйблены, поэтому нужный репозиторий указываем "на лету"):

# yum install --enablerepo=base usbutils

Получаем в итоге любимую lsusb - куда ж без неё в разборках с usb.

Вторым заходом ставим компилятор и make:

# yum install --enablerepo=base gcc make

Здесь yum спрашивает разрешение на обновление (кроме добавления) трёх системных компонент, glibc и др. Деваться некуда, разрешаем, всё ставится успешно.

Дальше всё традиционно - скачиваем исходник NUT-а последней версии:

# wget http://www.networkupstools.org/source/2 ... 6.1.tar.gz

Распаковываем во временную директорию, переходим туда и -- ключевой момент -- правильно конфигурируем. Т.к. XenServer - это сильно урезанная по сравнению с "обычным" linux-ом система, то я оставил только реально необходимые опции (н-р, выбросил поддержку snmp). Тут надо сказать, что NUT - это типичный linuxway, и за время своего существования программа не раз меняла предлагаемые имена служебного пользователя, группы, иерархию директорий и т.д. Я использовал для новой установки предлагаемые умолчания последней версии.

При установке из rpm-а нужные пользователь/группа создаются автоматом, при установке из исходников это приходится делать вручную - необходимо создать пользователя с именем ups, группу nut и сделать ups-а членом группы nut. Очень здорово, полно и толково все последующие действия описаны в HOWTO: nut, в частности создание нужного пользователя/группы там реализовано вот так:

# Add a 'ups' user and 'nut' group, if they don't already exist
# (I use those names only because the docs use those)
getent group | grep "^nut:" > /dev/null 2>&1 || groupadd nut
id ups > /dev/null 2>&1 || useradd -g nut -m ups


Красиво :). Но у меня была некоторая специфика и некоторые моменты я сделал удобнее. Когда я конфигурил исходники:

# ./configure --with-usb --without-neon --without-snmp --without-doc --with-user=ups --with-group=nut

то оказалось, что для работы драйвера usbhid-ups нужна devel версия библиотеки libusb. Ставим и её:

# yum install --enablerepo=base libusb-devel

После этого ./configure проходит без ошибок. Дальше стандартно: make; make install. Как оказалось, для XenServer было бы полезным указать ещё один ключ: --with-udev-dir=/etc/udev/rules.d, т.к. по современной моде по умолчанию директория для udev rules "живёт" в /lib/udev/rules.d. Но, даже если этого не сделать, файл 52-nut-usbups.rules потом можно без проблем перенести руками в /etc/udev/rules.d/.

В принципе, дальше можно делать всё точно по HOWTO: nut, получится вполне работоспособная конфигурация, но я решил сделать чуть более продвинутый вариант, с удобным скриптом запуска, сервисом и т.д. Для этого я позаимствовал из распакованных бинарных RPM-дистрибутивов NUT-а некоторые файлы. В частности файл /etc/sysconfig/ups:

# If the UPS is locally attached set it to "yes"
SERVER=yes
# Any options to pass to upsd
UPSD_OPTIONS=
# This *must* be the same as in /etc/ups/upsmon.conf
POWERDOWNFLAG=/etc/killpower
#


Скрипт запуска проверяет (и использует) этот файл и, если он отсутствует, то запуск произойдёт в slave-моде. Master-мода -- это когда UPS подключён непосредственно к компьютеру, а не "пасёт" статус UPS-а по сети (slave).

Скрипт запуска в /etc/init.d, назван ups, я использовал без переделок, т.к. в нём все пути совпадают с моими (хотя в комментариях упоминается /etc/ups, но это не так, правильный путь /usr/local/ups/etc). Т.е., вместо предлагаемого примитивного:

# Add something to /etc/rc.d/rc.local to start upsdrvctl, upsd,
# and upsmon on boot-up. Here's a basic example:
#if [ -d /usr/local/ups ]; then
# echo "Starting NUT..."
# /usr/local/ups/bin/upsdrvctl start
# /usr/local/ups/sbin/upsd
# /usr/local/ups/sbin/upsmon
#fi


я взял из бинарных RPM-ов готовый и более продвинутый скрипт для сервиса ups. К сожалению, на этом форуме нет тэга спойлер, а текст скрипта ups довольно большой и если я его сюда скопирую, текст сильно распухнет. Если кому-то реально потребуется, источник, где разжиться этим скриптом (он вполне стандартный), я указал.

В результате я запускаю/останавливаю систему стандартными командами:

# service ups start
# service ups stop


Также совершенно стандартно регистрируется сервис:

# chkconfig ups on

Все примеры конфигурационных файлов хорошо документированы, я приведу только некоторые важные строки из некоторых файлов:

ups.conf:
Код: Выделить всё
user = ups

[xen-home]
# USB
        driver = usbhid-ups
        port = auto
        desc = "Xensource host UPS"


upsmon.conf:
Код: Выделить всё
MONITOR xen-home@localhost 1 upsmon password master
...
POWERDOWNFLAG /etc/killpower
...
FINALDELAY 90


upsd.users:
Код: Выделить всё
[admin]
        password = secret
        actions = SET
        instcmds = ALL
...
[upsmon]
        password  = password
        upsmon master



А теперь о некоторых тонкостях/особенностях, с которыми пришлось столкнуться мне. Упоминавшийся выше файл правил 52-nut-usbups.rules используется для назначения нужных пермишеннов на USB-устройство, чтобы можно было доступаться к устройству, не имея root-вых прав. Стандартная техника, но у меня она почему-то не заработала сразу. Разборка показала, что проблема в строке:

ACTION!="add|change", GOTO="nut-usbups_rules_end"

Когда я её переделал на:

ACTION!="add", GOTO="nut-usbups_rules_end"

всё стало работать. Проблема в символе '|'. И буквально пару часов назад мне рассказали, что работа конструкции вида "add|change" зависит от версии udev: если она равна или выше 109 - будет работать такая запись, если ниже - нет. В XenServer-е версия udev - 095. По идее (проверено udevmonitor-ом) вполне достаточно обработать только add, но, если хочется сохранить обработку и change, то можно переписать правила как-то вот так (три первых строки и новая метка вместо одной строки с '|'):

ACTION=="add", GOTO="nut-usbups_rules_1"
ACTION=="change", GOTO="nut-usbups_rules_1"
ACTION!="add", GOTO="nut-usbups_rules_end"
###ACTION!="add|change", GOTO="nut-usbups_rules_end"

LABEL="nut-usbups_rules_1"

SUBSYSTEM=="usb_device", GOTO="nut-usbups_rules_real"
SUBSYSTEM=="usb", GOTO="nut-usbups_rules_real"
SUBSYSTEM!="usb", GOTO="nut-usbups_rules_end"

LABEL="nut-usbups_rules_real"
...


Ещё момент - при переходе на батареи (пропадание сети), практически сразу же, после (по умолчанию) 5-секундной задержки, начиналась процедура shutdown-а. То же самое происходило при подаче команды тестирования UPS-а. Расследование выявило, что как только UPS оказывается на батарее, то по команде чтения статуса он выдаёт:

# /usr/local/bin/upsc xen-home battery.charge
72

# /usr/local/bin/upsc xen-home ups.status
OB DISCHRG


Т.е., батарея имеет 72% заряда, но в статусе UPS-а говорится, что она разряжена (DISCHRG). И, поэтому, совершенно логично, начинается процедура shutdown-а. Вылечил я это установкой параметра FINALDELAY 90 (секунды) в файле upsmon.conf (вместо умолчательных 5 секунд). Причина, по которой при (почти) полностью заряженной батарее UPS немедленно отдаёт статус DISCHRG, сейчас выясняется - это или ошибка самого UPS-а или неверная интерпретация NUT-ом получаемого статуса. Буду смотреть исходники.

Вот, вроде бы пока всё. Наверное, стОит перенести это сообщение в "Грабли".

UPD1: Посмотрел исходники/доки - оказывается, статус DISCHRG означает "The battery is discharging (inverter is providing load power)", т.е., батарея РАЗРЯЖАЕТСЯ, а НЕ РАЗРЯЖЕНА. По идее процедура shutdown-а должна начинаться только по достижению уровня LOWBATT (после задержки FINALDELAY секунд) - в моём UPS-е это 10%. Похоже, ошибка в логике NUT-а - он начинает shutdown, как только видит статус OB ("На батарее") DISCHRG ("батарея разряжается").

UPD2: Ну вот же, в исходниках вроде всё правильно (upsmon.c):
Код: Выделить всё
/* not OB or not LB = not critical yet */
   if ((!flag_isset(ups->status, ST_ONBATT)) ||
      (!flag_isset(ups->status, ST_LOWBATT)))
      return 0;

и в man-е тоже вроде правильно описано:
Код: Выделить всё
fake_lowbatt

This forces the low battery flag true. Without it, if you want to test your UPS, you will have to unplug it and wait until the battery drops to a low/critical voltage level before NUT will respond and power down your system. With the flag, NUT should power down the system soon after you pull the plug. When you are done testing, you should remove this flag.
Аватара пользователя
Сергей Дубров
 
Сообщения: 2096
Зарегистрирован: 05 июн 2002, 06:07
Откуда: Новосибирск, ин-т ядерной физики СО РАН

Вернуться в Грабли

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

cron