Будем исходить из того, что наша распределённая файловая система на разнесённых по сети блочных устройствах сосредоточена в одном широковещательном сегменте и все обнаруженные AoE блоки подлежат импорту в локальную файловую систему сервера, сводящего блоки AoE в единое целое. В общем, всё, что обнаружим - будем пробовать подмонтировать.
В реализации модуля AoE для Debian Lenny/Squeeze есть парочка нюансов, которая оказала существенное влияние на методы контроля за нашей распределённой файловой системой. Во первых, автоматически не очищаются списки обнаруженных AoE устройств по таймауту, даже тогда, когда таковые явно не отвечают уже несколько часов. Во вторых, даже после того, как отсутствие связи с AoE-устройством обнаружено с помощью соответствующих утилит, оно отключено физически, прекращён экспорт и импорт этого устройства, на стороне сервера-сборщика ссылка на устройство освобождена от использования кем бы-то ни-было, устранены все причины, по которым это устройство могло бы понадобится, даже указание принудительного его удаления с помощью утилиты aoe-flush не гарантирует исчезновение этого устройства из списка доступных. Единственный способ гарантировано почистить изменившийся список, после модификации физических носителей информации, например - это размонтирование файловой системы, освобождение ссылок на AoE-устройства, выгрузка модуля AoE, загрузка его заново, поиск AoE устройств и сборка файловой системы заново.
# mkdir -p /var/log/aoe-import
Создаём подключаемый конфигурационный файл, в котором будут определены некоторые общие параметры, вроде: списка отрабатываемых устройств, из количества и тому подобного:
# vi /etc/default/aoe-import.conf
OBJECTS=""
# Количество импортируемых файловых систем
NUMBERFS="20"
# Перечень адресов электронных почтовых ящиков, на которые высылаются уведомления
EMAIL="mail@example.net"
# Количество импортируемых файловых систем
NUMBERFS="20"
# Перечень адресов электронных почтовых ящиков, на которые высылаются уведомления
EMAIL="mail@example.net"
Создаём непосредственно скрипт запуска импорта, включающий в себя функционал проверки состояния импортированных файловых систем и запуска соответстсвующих операций устранения последствий неисправностей:
# vi /etc/init.d/aoe-import && chmod ugo+x /etc/init.d/aoe-import
#! /bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
### BEGIN INIT INFO
# Provides: aoe-import
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start scripts import and assembly FS
# Description: start the import of remote FS and assembly them locally
### END INIT INFO
# Подключим файл с настройками
if [ -f /etc/custom/hdd/aoe-import.conf ]
then
. /etc/custom/hdd/aoe-import.conf
fi
HOSTNAME=`cat /etc/hostname`
# INTERFACE="eth0"
INTERFACE="bond0"
DATE=`date +"%Y-%m-%d %H:%M:%S"`
LOG=/var/log/aoe-import/aoe-import.log
# Определяем функцию уведомления администратора о нештатном развитии ситуации
function send-report() {
local LOCAL_OBJECT=$1
local LOCAL_REPORT=$2
# Посылаем электронное письмо с уведомлением о проблеме
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning AoE-import: ${HOSTNAME}: /dev/${LOCAL_OBJECT}\n${DATE}.\nHost: ${HOSTNAME}.\nDevice: /dev/${LOCAL_OBJECT}.\n${LOCAL_REPORT}" | sendmail -F${HOSTNAME} ${EMAIL}
return 0
}
# Определяем функцию проверки состояния корневой точки монтирования (MHDDFS) (к сожалению, по неясным причинам, иногда драйвер MHDDFS перестаёт отображать свою файловую систему в точку монтирования)
function check-mhddfs() {
# TEST=`df -h | grep -i "/mnt/storage" | grep -i "not connected"`
TEST=`df 2>&1 | grep -i "/mnt/storage" | grep -i "not connected"`
if [ "${TEST}" != "" ]
then
send-report "MHDDFS" "Warning! MHDDFS не отображает FS в точку монтирования."
echo >&2 "Warning! MHDDFS не отображает FS в точку монтирования."
return 1
fi
return 0
}
# Определяем функцию последовательных тестов доступности импортируемых блочных устройств
function check-import() {
# Проверяем факт запуска AoE по созданным им конструкциям
if [ ! -e /dev/etherd/discover ]
then
# Загружаем модуль AoE, если этого не было сделано ранее
echo "Waiting 3 seconds for correct load and configure module AoE..."
modprobe aoe
aoe-interfaces ${INTERFACE}
aoe-discover
sleep 3
if [ ! -e /dev/etherd/discover ]
then
send-report "AoE" "Warning! AoE не работает или работает некорректно."
echo >&2 "Warning! AoE не работает или работает некорректно."
return 1
fi
fi
# Закручиваем цикл в ожидании обнаружения всех импортируемых блочных устройств
COUNT="0"
aoe-discover
until [ "`ls -l /dev/etherd/ | grep -c '^brw'`" = "${NUMBERFS}" ]
do
sleep 1
let COUNT=${COUNT}+1
echo "Wait for discover all AoE devices... ${COUNT} sec."
if [ "${COUNT}" -gt "600" ]
then
# Паникуем, что за десять минут не обнаружены все ожидаемые блочные устройства
send-report "AoE-import" "Panic! Не все блочные устройства были импортированы в течении десяти минут."
echo >&2 "Не все блочные устройства были импортированы в течении десяти минут."
return 1
fi
aoe-discover
done
# Переходим в директорию, где располагаются импортируемые блочные устройства
cd /dev/etherd/
# Тестируем все импортируемые блочные устройства на предмет доступности
for OBJECT in *
do
# Проверяем, является ли файл блочным устройством
if [ -b "./${OBJECT}" ]
then
# Получаем в переменные назначенный устройству индекс
INDEXT=`echo "${OBJECT}" | cut -c 2-`
INDEXF=`echo ${INDEXT} | awk -F . '{print $1}'`
INDEXS=`echo ${INDEXT} | awk -F . '{print $2}'`
echo "${DATE}: e${INDEXF}.${INDEXS}" >> ${LOG}
# Проводим многократный тест, оценивая доступность устройства по суммарным показателям (на случай, если ответ от удалённого устройства задержался в связи с сильной загруженностью сетевой инфраструктуры, что бывает)
RETCOUNT="0"
for INDEX in 1 2 3 4 5 6
do
# Проверяем, доступно ли блочное устройство
aoeping -s 20 ${INDEXF} ${INDEXS} ${INTERFACE}
if [ "$?" != "0" ]
then
let RETCOUNT=${RETCOUNT}+1
fi
echo "$?" >> ${LOG}
done
# Вылавливаем значение количества ошибок: "больше либо равно"
if [ "${RETCOUNT}" -ge "5" ]
then
# Паникуем по поводу недоступности импортируемого устройства
send-report "${OBJECT}" "Panic! Импортируемое блочное устройство обнаружено, но не доступно."
echo >&2 "Panic! Импортируемое блочное устройство /dev/etherd/${OBJECT} обнаружено, но не доступно."
return 1
fi
fi
done
return 0
}
function start() {
# Тестируем AoE-устройства в ожидании полного набора
check-import
RETAOE=$?
# Проверяем, как успешно прошли тесты
if [ "${RETAOE}" = "0" ]
then
echo "AoE driver initialization and test remote block devices complete."
# Запускаем сбор файловой системы
/etc/custom/hdd/mnt/assembly-mnt.sh
# После сбора файловой системы запускаем пакет приложений, который на таковой работает
/etc/init.d/application0 start
/etc/init.d/application1 start
/etc/init.d/application2 start
else
# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/aoe/lock
exit 1
fi
return 0
}
function stop() {
# Останавливаем пакет приложений, который работает на сборной файловой системе
/etc/init.d/application0 stop
/etc/init.d/application1 stop
/etc/init.d/application2 stop
# Разбираем файловую систему, освобождая её ресурсы
/etc/custom/hdd/mnt/disassembly-mnt.sh
# Останавливаем работу AoE
modprobe -r aoe
echo "Wait..."
sleep 3
if [ -e /dev/etherd/discover ]
then
# Паникуем по поводу того, что модуль AoE не был выгружен несмотря на явное указание
send-report "AoE" "Warning! Модуль AoE не был выгружен, несмотря на явное указание."
echo >&2 "Warning! Модуль AoE не был выгружен, несмотря на явное указание."
return 1
fi
return 0
}
# Проверяем, не установлены ли флаги блокировки от текущего уровня схемы
if [ -e /tmp/custom/aoe/lock ]
then
exit 0
fi
# Устанавливаем флаг блокировки на время работы скрипта
mkdir -p /tmp/custom/aoe
touch /tmp/custom/aoe/lock
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
echo "Wait..."
sleep 1
start
;;
check)
# Тестируем подсистему MHDDFS
check-mhddfs
RETMHDDFS=$?
# Тестируем существующую подсистему AoE
check-import
RETAOE=$?
# В случае обнаружения несоответствия требуемому - перезапускаем сборку
if [ "${RETMHDDFS}" != "0" ] || [ "${RETAOE}" != "0" ]
then
stop
echo "Wait..."
sleep 1
start
fi
;;
*)
echo "Usage $0 {start|stop|restart|check}" >&2
# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/aoe/lock
exit 1
;;
esac
# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/aoe/lock
exit 0
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
### BEGIN INIT INFO
# Provides: aoe-import
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start scripts import and assembly FS
# Description: start the import of remote FS and assembly them locally
### END INIT INFO
# Подключим файл с настройками
if [ -f /etc/custom/hdd/aoe-import.conf ]
then
. /etc/custom/hdd/aoe-import.conf
fi
HOSTNAME=`cat /etc/hostname`
# INTERFACE="eth0"
INTERFACE="bond0"
DATE=`date +"%Y-%m-%d %H:%M:%S"`
LOG=/var/log/aoe-import/aoe-import.log
# Определяем функцию уведомления администратора о нештатном развитии ситуации
function send-report() {
local LOCAL_OBJECT=$1
local LOCAL_REPORT=$2
# Посылаем электронное письмо с уведомлением о проблеме
echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning AoE-import: ${HOSTNAME}: /dev/${LOCAL_OBJECT}\n${DATE}.\nHost: ${HOSTNAME}.\nDevice: /dev/${LOCAL_OBJECT}.\n${LOCAL_REPORT}" | sendmail -F${HOSTNAME} ${EMAIL}
return 0
}
# Определяем функцию проверки состояния корневой точки монтирования (MHDDFS) (к сожалению, по неясным причинам, иногда драйвер MHDDFS перестаёт отображать свою файловую систему в точку монтирования)
function check-mhddfs() {
# TEST=`df -h | grep -i "/mnt/storage" | grep -i "not connected"`
TEST=`df 2>&1 | grep -i "/mnt/storage" | grep -i "not connected"`
if [ "${TEST}" != "" ]
then
send-report "MHDDFS" "Warning! MHDDFS не отображает FS в точку монтирования."
echo >&2 "Warning! MHDDFS не отображает FS в точку монтирования."
return 1
fi
return 0
}
# Определяем функцию последовательных тестов доступности импортируемых блочных устройств
function check-import() {
# Проверяем факт запуска AoE по созданным им конструкциям
if [ ! -e /dev/etherd/discover ]
then
# Загружаем модуль AoE, если этого не было сделано ранее
echo "Waiting 3 seconds for correct load and configure module AoE..."
modprobe aoe
aoe-interfaces ${INTERFACE}
aoe-discover
sleep 3
if [ ! -e /dev/etherd/discover ]
then
send-report "AoE" "Warning! AoE не работает или работает некорректно."
echo >&2 "Warning! AoE не работает или работает некорректно."
return 1
fi
fi
# Закручиваем цикл в ожидании обнаружения всех импортируемых блочных устройств
COUNT="0"
aoe-discover
until [ "`ls -l /dev/etherd/ | grep -c '^brw'`" = "${NUMBERFS}" ]
do
sleep 1
let COUNT=${COUNT}+1
echo "Wait for discover all AoE devices... ${COUNT} sec."
if [ "${COUNT}" -gt "600" ]
then
# Паникуем, что за десять минут не обнаружены все ожидаемые блочные устройства
send-report "AoE-import" "Panic! Не все блочные устройства были импортированы в течении десяти минут."
echo >&2 "Не все блочные устройства были импортированы в течении десяти минут."
return 1
fi
aoe-discover
done
# Переходим в директорию, где располагаются импортируемые блочные устройства
cd /dev/etherd/
# Тестируем все импортируемые блочные устройства на предмет доступности
for OBJECT in *
do
# Проверяем, является ли файл блочным устройством
if [ -b "./${OBJECT}" ]
then
# Получаем в переменные назначенный устройству индекс
INDEXT=`echo "${OBJECT}" | cut -c 2-`
INDEXF=`echo ${INDEXT} | awk -F . '{print $1}'`
INDEXS=`echo ${INDEXT} | awk -F . '{print $2}'`
echo "${DATE}: e${INDEXF}.${INDEXS}" >> ${LOG}
# Проводим многократный тест, оценивая доступность устройства по суммарным показателям (на случай, если ответ от удалённого устройства задержался в связи с сильной загруженностью сетевой инфраструктуры, что бывает)
RETCOUNT="0"
for INDEX in 1 2 3 4 5 6
do
# Проверяем, доступно ли блочное устройство
aoeping -s 20 ${INDEXF} ${INDEXS} ${INTERFACE}
if [ "$?" != "0" ]
then
let RETCOUNT=${RETCOUNT}+1
fi
echo "$?" >> ${LOG}
done
# Вылавливаем значение количества ошибок: "больше либо равно"
if [ "${RETCOUNT}" -ge "5" ]
then
# Паникуем по поводу недоступности импортируемого устройства
send-report "${OBJECT}" "Panic! Импортируемое блочное устройство обнаружено, но не доступно."
echo >&2 "Panic! Импортируемое блочное устройство /dev/etherd/${OBJECT} обнаружено, но не доступно."
return 1
fi
fi
done
return 0
}
function start() {
# Тестируем AoE-устройства в ожидании полного набора
check-import
RETAOE=$?
# Проверяем, как успешно прошли тесты
if [ "${RETAOE}" = "0" ]
then
echo "AoE driver initialization and test remote block devices complete."
# Запускаем сбор файловой системы
/etc/custom/hdd/mnt/assembly-mnt.sh
# После сбора файловой системы запускаем пакет приложений, который на таковой работает
/etc/init.d/application0 start
/etc/init.d/application1 start
/etc/init.d/application2 start
else
# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/aoe/lock
exit 1
fi
return 0
}
function stop() {
# Останавливаем пакет приложений, который работает на сборной файловой системе
/etc/init.d/application0 stop
/etc/init.d/application1 stop
/etc/init.d/application2 stop
# Разбираем файловую систему, освобождая её ресурсы
/etc/custom/hdd/mnt/disassembly-mnt.sh
# Останавливаем работу AoE
modprobe -r aoe
echo "Wait..."
sleep 3
if [ -e /dev/etherd/discover ]
then
# Паникуем по поводу того, что модуль AoE не был выгружен несмотря на явное указание
send-report "AoE" "Warning! Модуль AoE не был выгружен, несмотря на явное указание."
echo >&2 "Warning! Модуль AoE не был выгружен, несмотря на явное указание."
return 1
fi
return 0
}
# Проверяем, не установлены ли флаги блокировки от текущего уровня схемы
if [ -e /tmp/custom/aoe/lock ]
then
exit 0
fi
# Устанавливаем флаг блокировки на время работы скрипта
mkdir -p /tmp/custom/aoe
touch /tmp/custom/aoe/lock
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
echo "Wait..."
sleep 1
start
;;
check)
# Тестируем подсистему MHDDFS
check-mhddfs
RETMHDDFS=$?
# Тестируем существующую подсистему AoE
check-import
RETAOE=$?
# В случае обнаружения несоответствия требуемому - перезапускаем сборку
if [ "${RETMHDDFS}" != "0" ] || [ "${RETAOE}" != "0" ]
then
stop
echo "Wait..."
sleep 1
start
fi
;;
*)
echo "Usage $0 {start|stop|restart|check}" >&2
# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/aoe/lock
exit 1
;;
esac
# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/aoe/lock
exit 0
После отработки публикующего (экспортирующего) скрипта в директориях "/dev/etherd/" всех компьютеров в одном сегменте сети Ethernet с запущенным AoE можно будет обнаружить ссылки на автоматически обнаруженные блочные устройства AoE, например:
# ls -l /dev/etherd/ | grep b
....
brw-rw--- 1 root disk 152, 16 2010-05-31 17:25 e0.1
brw-rw--- 1 root disk 152, 48 2010-05-31 17:25 e0.3
....
brw-rw--- 1 root disk 152, 48 2010-05-31 17:25 e4.7
....
brw-rw--- 1 root disk 152, 16 2010-05-31 17:25 e0.1
brw-rw--- 1 root disk 152, 48 2010-05-31 17:25 e0.3
....
brw-rw--- 1 root disk 152, 48 2010-05-31 17:25 e4.7
....
Теперь нужно сделать так, что бы наш скрипт запускался при старте системы, причём пораньше, но после старта основных сервисов. Система инициализации Debian отрабатывает скрипты "/etc/init.d/*" по ссылкам в директории соответствующего "ранлевела" (для Debian Lenny/Squeeze это второй уровень исполнения), последовательно, приступая к делу с тех, что начинаются с буквы "K" (условно "kill"), посылая им аргумент "stop", и заканчивая исполнением тех, что начинаются с буквы "S" (условно "start"), посылая им аргумент "start". Подсмотрим, какой порядковый номер у ссылки на сценарий запуска сервиса SSH - "S18", я подумал, что для скрипта запуска сборки файловой системы номер "S19" будет в самый раз; срузу после SSH, если что - сможем посмотреть, что к чему.
Прописываем наш скрипт для нужных уровней исполнения в системе:
# update-rc.d aoe-import start 18 2 3 4 5 . stop 18 0 1 6 .
Размещаем команду запуска скрипта периодической проверки состояния в таблице /etc/crontab:
# vi /etc/crontab
....
*/7 * * * * root /etc/init.d/aoe-import check &
....
*/7 * * * * root /etc/init.d/aoe-import check &
....
Переход к настройке сбора нескольких файловых систем в единой точке монтирования.