Ключевые слова:freebsd, windows, ups, (найти похожие документы)
From: Рашид Ачилов
Date: Mon, 15 Feb 2010 17:02:14 +0000 (UTC)
Subject: Один UPS на двоих - FreeBSD в домене Windows
Материал предоставлен редакцией журнала Системный администратор.
Опубликовано в журнале "Системный администратор" N 12 2009
Ситуация, когда к одному UPS подключено несколько серверов, - не
исключение, а скорее правило. Как вовремя отключить сервер, если
программа для работы с данным UPS существует только для Windows?
И вольт 220 - и то пополам...
На сегодняшний день существует широкий диапазон устройств, способных
обеспечивать резервное питание серверов в той мере, в которой это
необходимо. Далеко не ко всем устройствам (а точнее говоря только к UPS
производства APC [1]) существуют клиенты под FreeBSD, позволяющие
принимать по сети сообщения от сетевых UPS и соответственно
обрабатывать их. Как поступить в том случае, если имеется только клиент
под Windows, а необходимо запрограммировать реакцию на сообщение UPS о
том, что необходимо прервать работу в связи с пропаданием питания?
Моделировать ситуацию будем в следующих условиях - имеется UPS
Powerware 9120 [2], к которому подключены компьютер под управлением
Windows и компьютер под управлением FreeBSD. Управление UPS
осуществляется через поставляемый вместе с UPS кабель RS-232 с
компьютера с ОС Windows, на котором установлено программное обеспечение
LanSafe. LanSafe можно бесплатно скачать непосредственно с сайта
производителя [2]. Требуется - при долговременном пропадании питания
вместе с корректным завершением работы сервера под управлением ОС
Windows корректно завершать работу сервера под управлением FreeBSD.
Задача эта на самом деле решается достаточно просто в том случае, когда
программное обеспечение для управления UPS имеет возможность по
наступлению некоторого события выполнять определенную внешнюю команду.
Уже упомянутый выше LanSafe имеет возможность на каждое событие (а их
достаточно много) настроить три вида реакции - оповещение по почте,
оповещение широковещательным сообщением и выполнение внешней команды,
причем все виды реакции можно настраивать независимо друг от друга.
Таким образом, обработка события Power failure (пропадание напряжения
питания), которое возникает в том случае, если исчезает напряжение
питания, будет происходить согласно следующей схеме (см. рис. 1).
Рисунок 1. Последовательность обработки события UPS для двух серверов
Для реализации данной схемы нам понадобится, кроме самого LanSafe:
* Для Windows - программа удаленного выполнения команд по протоколу
SSH plink.exe и программа генерации ключей SSH (входят в состав
бесплатного SSH-клиента PuTTY, скачать можно с [3]).
* Для FreeBSD - программа выполнения команды от имени другого
пользователя sudo (ports/security/sudo) и SSH-сервер для приема и
обработки команды. Можно использовать стандартный OpenSSH, но я
предпочитаю сервер от SSH Communication Inc.
(ports/security/ssh2-nox11).
Итак, в общем случае задача может быть сформулирована так: "Как из
одной программы запустить другую на удаленном сервере". Сформулировав
же задачу в общем виде, переходим к частностям.
Частности
Подробности реализации мы начнем рассматривать с последнего звена
цепочки - с сервера FreeBSD. Чтобы отправить на него команду,
необходимо, чтобы кто-то эту команду принял. Этот "кто-то" будет у
нас псевдопользователем (то есть пользователем, не имеющим пароля, но
имеющим допустимый шелл) upsadmin.
Создаем учетную запись пользователя:
# pw useradd upsadmin -d /usr/home/upsadmin -m -s /bin/sh -c "UPS administrator" -h -
В случае успешного завершения команда pw не выводит ничего.
Переключаемся на учетную запись этого пользователя (то, что все это
выполняется от пользователя root, я думаю, упоминать излишне) и
настраиваем SSH для использования беспарольной авторизации по
публичному ключу:
# su -l upsadmin
# ssh-keygen2 -t dsa
Generating 2048-bit dsa key pair
3 o.oOo..oOo.o
Key generated.
2048-bit dsa, [email protected], Wed Oct 28 2009 00:37:39 +0600
Passphrase :
Again :
Key is stored with NULL passphrase.
(You can ignore the following warning if you are generating hostkeys.)
This is not recommended. Don't do this unless you know what you're doing.
If file system protections fail (someone can access the keyfile),
or if the super-user is malicious, your key can be used without
the deciphering effort.
Private key saved to /usr/home/upsadmin/.ssh2/id_dsa_2048_a
Public key saved to /usr/home/upsadmin/.ssh2/id_dsa_2048_a.pub
Предупреждение о возможном нарушении политики безопасности, при которой
каждый личный ключ из пары ключей должен быть защищен паролем (а иначе
злоумышленник, получивший доступ к нему, сможет им воспользоваться),
игнорируем - мы не будем пользоваться собственными ключами пользователя
upsadmin.
Переходим в каталог .ssh2 (он будет создан автоматически) и создаем два
пустых файла - identification и authorization.
В файл identification прописываем строку:
IdKey id_dsa_2048_a
Файл authorization пока не трогаем, он нам понадобится потом.
Далее наделяем пользователя upsadmin правами на выключение и
перезагрузку компьютера. Устанавливаем пакет sudo, если он не
установлен, и прописываем в файле /usr/local/etc/sudoers (он будет
автоматически создан и заполнен примерами) следующие строки:
# Cmnd alias specification
Cmnd_Alias SHUTDOWN = /sbin/shutdown
Cmnd_Alias HALT = /sbin/halt
Cmnd_Alias REBOOT = /sbin/reboot
Cmnd_Alias IPFW = /sbin/ipfw
# UPS remote command executor
upsadmin ALL=(root) NOPASSWD: SHUTDOWN, NOPASSWD: HALT, NOPASSWD: REBOOT, NOPASSWD: IPFW
Последняя команда (IPFW) нам понадобится только для тестирования, после
того как все будет отлажено, ее можно и нужно убрать. Что мы описали
данными строками? Мы описали, что при выполнении через sudo команд
shutdown, halt, reboot и ipfw пользователь upsadmin по уровню
привилегий равен администратору (root) и при выполнении этих команд ему
нет необходимости вводить свой пароль.
Проверяем.
# su -l upsadmin
$ sudo ipfw sh
ipfw: DEPRECATED: 'sh' matched 'show' as a sub-string
... (вывод удален)
65000 0 0 allow ip from any to any
65535 457 45540 deny ip from any to any
Отлично. Теперь создадим предыдущий элемент схемы - скрипт, который
будет выдавать команду выключения питания. Выполняться этот скрипт
будет от пользователя upsadmin. Для того чтобы не указывать
расположение скрипта, просто создадим в домашнем каталоге пользователя
upsadmin каталог bin.
Почему именно bin? Мы указали /bin/sh в качестве стартового шелла. При
запуске /bin/sh автоматически выполняется его стартовый скрипт - файл
.profile в домашнем каталоге пользователя (подробнее - man sh). Файл
.profile, как правило, содержит следующую строку:
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:$HOME/bin; export PATH
Эта строка определяет, где /bin/sh будет искать программу в том случае,
если она запускается без указания пути. Проверьте, что PATH содержит
$HOME/bin. Разумеется, можно создать каталог с другим именем и указать
его имя в PATH или вообще не создавать ничего и каждый раз указывать
полный путь.
Сам скрипт - это всего лишь две строчки:
#!/bin/sh
logger -i -p local6.info -t lansafe Shutdown started
sudo shutdown -p now
Первая строка добавлена исключительно для удобства - при выполнении
скрипта всякий раз в файл, определяемый /etc/syslog.conf как local6,
будут записываться сообщения о причине выключения. Предварительно
необходимо определить в /etc/syslog.conf facility local6, например,
следующим образом:
local6.* /var/log/powerdown
При этом все сообщения с facility local6 будут направляться в файл
/var/log/powerdown. Строго говоря, пример не совсем корректный, так как
в этот файл могут быть направлены сообщения от любой программы,
присвоившей своим сообщениям facility local6. Для большей корректности
следовало бы написать так:
!lansafe
local6.* /var/log/powerdown
Ну вот, теперь достаточно запустить скрипт powerdown (так называется
файл скрипта) - питание будет выключено. Переходим еще левее по схеме -
к скрипту, выполняемому на Windows. Вот здесь нам и понадобится
заполнить файл authorization в каталоге .ssh2. Прописываем в него такую
строчку:
Key winbox.pub
Прописывается сюда имя файла публичного ключа, по которому будет
выполняться авторизация. Файл этот, разумеется, сначала должен быть
создан. Причем именно на том компьютере, с которого будет запускаться
команда, в нашем случае на том, к которому подключен UPS. Вот для этого
нам и понадобится программа puttygen.exe, которая в PuTTY играет роль,
аналогичную команде ssh2-keygen, Запускаем и создаем личный и общий
ключи (см. рис. 2).
Рисунок 2. Создание пары ключей с помощью программы puttygen.exe
Сохраняем файлы winbox.ppk (приватный ключ) и winbox.pub (публичный
ключ). Пароль на приватный ключ не устанавливаем. Мы используем
авторизацию по публичному ключу только для того, чтобы избежать задания
паролей в открытом тексте. Какой же нам смысл задавать пароль на ключ,
который все равно потребуется указывать в открытом виде?
Файл winbox.pub распространяем свободно - в частности, его нужно
поместить в подкаталог .ssh2 домашнего каталога пользователя upsadmin
на сервере FreeBSD. Файл же winbox.ppk оберегайте насколько возможно -
именно он является аналогом пароля. Хищение приватного ключа, не
защищенного паролем, автоматически означает, что любой сможет выдать
себя за лицо, которое этим ключом авторизуется. Разумеется, это
недостаток данного способа, но... за удобство надо чем-то платить?
После этого мы можем, запуская программу plink.exe, выполнять команды
на сервере FreeBSD от имени того пользователя, которое указываем, в
нашем случае upsadmin (см. рис. 3):
echo "Testing connection on UNIX server..."
plink.exe -ssh -P 22 -2 -i winbox.ppk [email protected] ls -la
Подробно все ключи к команде plink описаны в документации на PuTTY -
файле putty.chm.
Создаем для файлов отдельный каталог, например c:\upsmgmt, и переносим
в него все файлы, что нам понадобятся: приватный ключ winbox.ppk,
программу plink.exe. Сюда же можно положить и публичный ключ
winbox.pub.
И наконец, пишем собственно сам скрипт:
с:
cd \upsmgmt
plink.exe -ssh -P 22 -2 -i winbox.ppk [email protected] "powerdown"
Относительно этого скрипта следует сделать несколько замечаний.
* Во-первых, когда мы запускаем скрипт вручную, он запускается в том
каталоге, в котором мы в данный момент находимся. Когда же скрипт будет
запущен программой LanSafe, то он запустится в том каталоге, который
Windows полагает "по умолчанию". Скорее всего, это не будет
интересующий нас каталог, потому перед запуском команды необходимо явно
указать переход в нужный нам каталог (в примере c:\temp\2).
* Во-вторых, powerdown - не стандартная команда FreeBSD, а имя
скрипта, который мы создали на предыдущих шагах. Этот скрипт лежит в
%HOME%/bin, потому путь к нему можно не указывать.
Что ж, осталось последнее. Сохраняем скрипт в файл, например
testlink.bat, и помещаем его в тот каталог, в который делаем переход (в
примере c:\upsmgmt).
Запускаем программу LanSafe, выбираем пункт Configuration -> Event
Notification и в настройках для события Power failure задаем выполнение
команды c:\upsmgmt\testlink.bat с задержкой в 5 секунд (такая короткая
задержка только для тестирования, в реальной жизни, конечно же,
задержка должна быть больше) (см. рис. 4).
Рисунок 4. Настройка LanSafe на выполнение команды при пропадании питания
Все. Цепочка замкнулась. При возникновении события Power failure после
заданной задержки будет запущен скрипт testlink.bat, который запустит
plink.exe, который запустит powerdown на удаленном сервере, который в
свою очередь запустит команду "shutdown -p now".
К особенностям поведения здесь можно отнести одну вещь - при первом
запуске скрипта непосредственно самим LanSafe plink.exe выдает запрос
на кэширование ключа узла (точно так же, как он это делает всегда при
первом подключении). Все бы ничего, но только нужно учитывать тот факт,
что запрос этот выдается исключительно на консоль сервера Windows.
Если настраивать LanSafe, находясь в терминальной сессии, запроса мы не
увидим до тех пор, пока не перехватим консоль с помощью программ NetOp
или Radmin, поэтому перед тем как начинать эксплуатацию системы,
необходимо провести тестовый запуск, для чего в настройках LanSafe есть
кнопка Test, позволяющая вручную имитировать наступление тестируемого
события.
Существуют ли альтернативы описанному способу? Да, компания Eaton
выпускает LanSafe не только для операционных систем Windows, но и для
Linux тоже [4], в списке поддерживаемых дистрибутивов - Red Hat версии
3 (ESи AS), версии 4 и 5 (ES, AS и Desktop), Fedora Core версии 5-8 и
SuSE версии 8-10 (в том числе и Enterprise Linux Server). Вполне
возможно попробовать его запустить, установив модуль совместимости с
Linux-программами (ports/emulators/lunux-base-f7 или
ports/emulators/linux-base-f8). При этом прием оповещения от
контроллера UPS настраивается стандартным способом.
Описанный здесь способ - это всего лишь еще одна "малая механизация",
набор несложных инструментов, который один раз настраиваешь на
совершение определенных действий - и про них можно навсегда забыть,
скрипты будут выполняться, серверы выключаться в нужное время... И дом,
который построил Джек, не рухнет, по крайней мере, из-за неверного
выключения питания.
1. Сайт American Power Conversion, производителя UPS APC - http://www.apcc.com
2. Сайт Eaton, производителя UPS Powerware - http://powerquality.eaton.com/Russia/?cx=67
3. Сайт программы PuTTY - http://www.putty.org
4. Ссылка для загрузки LanSafe версии 6 -
http://powerquality.eaton.com/Support/Software-Drivers/Downloads/lansafe6.asp
а можно ли заставить срабатывать нужную команду не на power failure а например отследить как нибудь состояние батареи в процентах и тогда когда оно достигнет определенного уровня сделать доброе дело?
просто я даже самим итоновцам писал -фигушки сказали такое не возможно.
Но ведь тогда мы должны покупать ибп из расчета того, чтобы только выключиться.
А если надо держаться из всех сил, что тогда ?
вот на этом у меня и закончились все аргументы в сторону eaton & lansafe, которые мне сначала понравились даже больше apc power shute(standart edition of course)
UPS — это источник АВАРИЙНОГО питания. "Держаться из всех сил" для таких источников неприменимо в принципе. Для них главное корректно завершить работу поддерживаемого оборудования при пропадании основного питания.
Теоретически, можно. Хотя все зависит от модели ИБП (точнее от драйвера). Например, драйвер megatec поддерживает параметр lowbatt=... в ups.conf. Т.е. в твоем примере можно поставить lowbatt=20. А драйвер apcsmart (большинство моделей APC) такого параметра не поддерживает, зато по upsc выдает значения battery.charge (процент заряда батарей) и (еще лучше) позволяет с помощью upsrw задать значение battery.runtime.low (расчетное оставшееся время работы на батареях, при котором переходить в режим LowBattery). Дальше - дело техники.
Сразу скажу - на практике не пробовал. У меня работает по стандартной схеме: авария питания - 10 мин. на батареях - кладутся слейвы - кладется мастер - выключаются ИБП
>Теоретически, можно. Хотя все зависит от модели ИБП (точнее от драйвера). Например,
>драйвер megatec поддерживает параметр lowbatt=... в ups.conf. Т.е. в твоем примере
>можно поставить lowbatt=20. А драйвер apcsmart (большинство моделей APC) такого параметра
>не поддерживает, зато по upsc выдает значения battery.charge (процент заряда батарей)
>и (еще лучше) позволяет с помощью upsrw задать значение battery.runtime.low (расчетное
>оставшееся время работы на батареях, при котором переходить в режим LowBattery).
>Дальше - дело техники.
>Сразу скажу - на практике не пробовал. У меня работает по стандартной
>схеме: авария питания - 10 мин. на батареях - кладутся слейвы
>- кладется мастер - выключаются ИБП
т.е. если у меня будет megatec драйвер, то делаю через параметр и обработку события low battery
не много не понял ;(
забыл я уже что такое upsc
можно за значение следить и обрабатывать его правильно ?
интересно по поводу upsrw оно какие упсы поддерживает и вообще оно устанавливает значение это в памяти упса да ?
просто в моем случае с eaton 9130 мне из техподдержки ответили, что "battery.runtime.low" поменять незя ;(
Для всего, отличного от APC - юзать nut. А так - что одно, что второе - работает, кушать не просит. Хотя, при правильном планировании электропитания, стоит брать ормальные сетевые модели, с ними меньше всего геморроя. Про геморрой подобный знаю не на словах - было дело, обновил как-то на фре apcupsd на 2 минорные версии. Виндовый демон на 3х серверах отвалился. Откатился на фре, пересобрал под mingw новый для винды, обновил порт на фре, обновился на виндах.