Скрипты, конфигурационные и журнальные файлы нашей самодельной сетевой файловой системы будут располагаться одинаково на всех серверах, как ведущих, так и ведомых:
# mkdir -p /usr/local/etc/default/ /usr/local/etc/storage/fnc.d/ /usr/local/etc/storage/cnf.d/ /var/log/storage
Прежде всего создаём конфигурационный файл с параметрами для скрипта автоматизации:
# vi /usr/local/etc/default/storage-custom
# Default configuration file for /etc/init.d/storage-control
# Адрес директории динамически включаемых в тело скрипта управления описаний функций
FNCDIR="/usr/local/etc/storage/fnc.d"
# Адрес директории индивидуальных конфигураций сервисов хранилища
CNFDIR="/usr/local/etc/storage/cnf.d"
# Адрес директории файлов блокировок сервисов хранилища
LOCK="/tmp/storage/lck"
# Адрес файла журнала
LOG="/var/log/storage/default.log"
EMAIL=`cat /usr/local/etc/storage/email >/dev/null 2>&1`
# Адрес директории динамически включаемых в тело скрипта управления описаний функций
FNCDIR="/usr/local/etc/storage/fnc.d"
# Адрес директории индивидуальных конфигураций сервисов хранилища
CNFDIR="/usr/local/etc/storage/cnf.d"
# Адрес директории файлов блокировок сервисов хранилища
LOCK="/tmp/storage/lck"
# Адрес файла журнала
LOG="/var/log/storage/default.log"
EMAIL=`cat /usr/local/etc/storage/email >/dev/null 2>&1`
Пишем скрипт автоматизации контроля подсистемы хранения:
# vi /etc/init.d/storage-control && chmod ugo+rx /etc/init.d/storage-control
#!/bin/bash
### BEGIN INIT INFO
# Provides: storage-control
# Required-Start: $local_fs $syslog $network
# Required-Stop: $local_fs $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Script management of storage
# Description: Script management of storage
### END INIT INFO
# Подключаем первичный конфигурационный файл
source "/usr/local/etc/default/storage-custom"
[ ${?} -ne 0 ] && { echo "Fatal error: missing default custom storage configuration file. Operation aborted."; exit 1; }
# Принимаем в переменные с "говорящими" именами входящие аргументы
INSTANCE=${0}
OPERATION=${1}
TARGET=${2}
DATE=`date +"%Y-%m-%d %H:%M:%S"`
# Перебираем в цикле все объекты (по маске) в целевой директории динамически подключаемых описаний функций
cd "${FNCDIR}"
for OBJECT in *\.fnc ; do
# Включаем в тело скрипта текст обнаруженных фрагментов описаний функций
[ -f "${FNCDIR}/${OBJECT}" ] && source "${FNCDIR}/${OBJECT}"
done
# Создаём директорию для файлов блокировки
mkdir -p "${LOCK}"
# Определяем функцию предварительной инициализации конфигурационных файлов хранилища
function start-init() {
# Создаём временный файл журнала событий
LOGT=$(mktemp /tmp/storage-start.log.XXXXXXXX)
# Создаём временный файл глобальной конфигурации
CNF=$(mktemp /tmp/storage.cnf.XXXXXXXX)
cd "${CNFDIR}"
for OBJECT in *\.cnf ; do
# Включаем в тело временного глобального файла все обнаруженные фрагменты конфигураций
[ -f "${CNFDIR}/${OBJECT}" ] && cat "${CNFDIR}/${OBJECT}" >> "${CNF}"
done
DATE=`date +"%Y-%m-%d %H:%M:%S"`
start
# Если запуск системы хранилища завершился неудачно, то отсылаем отчёт и "разбираем" его
if [ "${?}" -ne "0" ] ; then
send-report "Storage assembling error!" "$(cat ${LOGT})"
return 1
fi
# Включаем временный журнал событий в основной и удаляем временный
cat "${LOGT}" >> "${LOG}"
rm --force "${LOGT}"
# Удаляем временный файл глобальной конфигурации
rm --force "${CNF}"
return ${?}
}
# Определяем функцию предварительной инициализации конфигурационных файлов хранилища
function stop-init() {
# Создаём временный файл журнала событий
LOGT=$(mktemp /tmp/storage-stop.log.XXXXXXXX)
# Создаём временный файл глобальной конфигурации
CNF=$(mktemp /tmp/storage.cnf.XXXXXXXX)
cd "${CNFDIR}"
for OBJECT in *\.cnf ; do
# Включаем в тело временного глобального файла все обнаруженные фрагменты конфигураций
[ -f "${CNFDIR}/${OBJECT}" ] && cat "${CNFDIR}/${OBJECT}" >> "${CNF}"
done
DATE=`date +"%Y-%m-%d %H:%M:%S"`
stop
# Если остановка системы хранилища завершилась неудачно, то отсылаем отчёт
if [ "${?}" -ne "0" ] ; then
send-report "Storage disassembling error!" "$(cat ${LOGT})"
fi
# Включаем временный журнал событий в основной и удаляем временный
cat "${LOGT}" >> "${LOG}"
rm --force "${LOGT}"
# Удаляем временный файл глобальной конфигурации
rm --force "${CNF}"
return ${?}
}
# Описываем функцию формирования опций хранилища и непосредственного её запуска
function start() {
echo | tee -a "${LOGT}"
echo "${DATE}: Procedure is running store is initialized." | tee -a "${LOGT}"
echo | tee -a "${LOGT}"
# Сборка массивов
declare -f start-mdadm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки RAID." | tee -a "${LOGT}"
else
start-mdadm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Assembly arrays failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Активация групп томов LVM
declare -f start-lvm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки LVM." | tee -a "${LOGT}"
else
start-lvm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Activating LVM volume groups failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Создание символической ссылки на заданный раздел целевого диска
declare -f make-symlink >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция создания символической ссылки на раздел целевого диска." | tee -a "${LOGT}"
else
make-symlink
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Create a symbolic link with error. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Монтирование локальных файловых систем хранилища
declare -f start-fs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция монтирования локальных файловых систем хранилища." | tee -a "${LOGT}"
else
start-fs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Mounting file systems store with error. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Публикация файловых систем хранилища посредством NFS
declare -f start-nfs-export >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция публикации файловых систем посредством NFS." | tee -a "${LOGT}"
else
start-nfs-export
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Publication of file systems via NFS storage failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Сборка файловых систем хранилища из ресурсов NFS
declare -f start-nfs-import >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки файловых систем из ресурсов NFS." | tee -a "${LOGT}"
else
# Учитывая то, что нам неизвестно, когда станут доступными все импортируемые ресурсы, закручиваем бесконечный цикл в ожидании полностью безошибочного импорта всех ресурсов
STERR=""
while [ "${STERR}" != "0" ] ; do
# Ждём некоторое время, перед повторением операции (кроме первой итерации)
[ ! -z "${STERR}" ] && sleep 10
start-nfs-import
STERR="${?}"
done
# Проверяем успешность завершения функции импортирования
if [ "${STERR}" -ne "0" ] ; then
echo "${DATE}: The assembly of the storage file system NFS resource failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Сборка файловых систем в единую точку монтирования
declare -f start-mhddfs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки файловых систем в единой точке монтирования." | tee -a "${LOGT}"
else
start-mhddfs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Assembly file systems into a single mount point failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
return ${?}
}
# Определяем функцию остановки хранилища
function stop() {
echo | tee -a "${LOGT}"
echo "${DATE}: Running stop procedure storage." | tee -a "${LOGT}"
echo | tee -a "${LOGT}"
# Разборка файловых систем, смонтированных в единую точку монтирования
declare -f stop-mhddfs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция разборки файловых систем в единой точке монтирования." | tee -a "${LOGT}"
else
stop-mhddfs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Disassembly of file systems mounted in a single mount point failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Разборка файловых систем хранилища из ресурсов NFS
declare -f stop-nfs-import >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция разборки файловых систем из ресурсов NFS." | tee -a "${LOGT}"
else
stop-nfs-import
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Disassembly of the storage file system NFS resource failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Отключение публикации файловых систем хранилища посредством NFS
declare -f stop-nfs-export >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция публикации файловых систем посредством NFS." | tee -a "${LOGT}"
else
stop-nfs-export
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Disabling Publishing file systems via NFS storage failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Демонтирование файловых систем хранилища
declare -f stop-fs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция демонтирования локальных файловых систем хранилища." | tee -a "${LOGT}"
else
stop-fs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Unmounting file systems store with error. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Деактивация групп томов LVM
declare -f stop-lvm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция деактивации групп томов LVM хранилища." | tee -a "${LOGT}"
else
stop-lvm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Deactivating LVM volume groups failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Остановка массивов
declare -f stop-mdadm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция деактивации RAID." | tee -a "${LOGT}"
else
stop-mdadm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Stop array failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
return ${?}
}
# Блок выбора варианта исполнения скрипта
case "$1" in
start)
start-init
# В случае ошибочного завершения сборки хранилища разбираем его
if [ "${?}" -ne "0" ] ; then
stop-init
fi
;;
stop)
stop-init
;;
check)
echo | tee -a "${LOGT}"
echo "${DATE}: Running the test procedure component." | tee -a "${LOGT}"
echo | tee -a "${LOGT}"
check-mdadm
check-lvm
check-fs
check-nfs-export
check-nfs-import
check-mhddfs
;;
*)
echo "Usage $0 {start|stop|check}" >&2
exit 1
;;
esac
exit $?
### BEGIN INIT INFO
# Provides: storage-control
# Required-Start: $local_fs $syslog $network
# Required-Stop: $local_fs $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Script management of storage
# Description: Script management of storage
### END INIT INFO
# Подключаем первичный конфигурационный файл
source "/usr/local/etc/default/storage-custom"
[ ${?} -ne 0 ] && { echo "Fatal error: missing default custom storage configuration file. Operation aborted."; exit 1; }
# Принимаем в переменные с "говорящими" именами входящие аргументы
INSTANCE=${0}
OPERATION=${1}
TARGET=${2}
DATE=`date +"%Y-%m-%d %H:%M:%S"`
# Перебираем в цикле все объекты (по маске) в целевой директории динамически подключаемых описаний функций
cd "${FNCDIR}"
for OBJECT in *\.fnc ; do
# Включаем в тело скрипта текст обнаруженных фрагментов описаний функций
[ -f "${FNCDIR}/${OBJECT}" ] && source "${FNCDIR}/${OBJECT}"
done
# Создаём директорию для файлов блокировки
mkdir -p "${LOCK}"
# Определяем функцию предварительной инициализации конфигурационных файлов хранилища
function start-init() {
# Создаём временный файл журнала событий
LOGT=$(mktemp /tmp/storage-start.log.XXXXXXXX)
# Создаём временный файл глобальной конфигурации
CNF=$(mktemp /tmp/storage.cnf.XXXXXXXX)
cd "${CNFDIR}"
for OBJECT in *\.cnf ; do
# Включаем в тело временного глобального файла все обнаруженные фрагменты конфигураций
[ -f "${CNFDIR}/${OBJECT}" ] && cat "${CNFDIR}/${OBJECT}" >> "${CNF}"
done
DATE=`date +"%Y-%m-%d %H:%M:%S"`
start
# Если запуск системы хранилища завершился неудачно, то отсылаем отчёт и "разбираем" его
if [ "${?}" -ne "0" ] ; then
send-report "Storage assembling error!" "$(cat ${LOGT})"
return 1
fi
# Включаем временный журнал событий в основной и удаляем временный
cat "${LOGT}" >> "${LOG}"
rm --force "${LOGT}"
# Удаляем временный файл глобальной конфигурации
rm --force "${CNF}"
return ${?}
}
# Определяем функцию предварительной инициализации конфигурационных файлов хранилища
function stop-init() {
# Создаём временный файл журнала событий
LOGT=$(mktemp /tmp/storage-stop.log.XXXXXXXX)
# Создаём временный файл глобальной конфигурации
CNF=$(mktemp /tmp/storage.cnf.XXXXXXXX)
cd "${CNFDIR}"
for OBJECT in *\.cnf ; do
# Включаем в тело временного глобального файла все обнаруженные фрагменты конфигураций
[ -f "${CNFDIR}/${OBJECT}" ] && cat "${CNFDIR}/${OBJECT}" >> "${CNF}"
done
DATE=`date +"%Y-%m-%d %H:%M:%S"`
stop
# Если остановка системы хранилища завершилась неудачно, то отсылаем отчёт
if [ "${?}" -ne "0" ] ; then
send-report "Storage disassembling error!" "$(cat ${LOGT})"
fi
# Включаем временный журнал событий в основной и удаляем временный
cat "${LOGT}" >> "${LOG}"
rm --force "${LOGT}"
# Удаляем временный файл глобальной конфигурации
rm --force "${CNF}"
return ${?}
}
# Описываем функцию формирования опций хранилища и непосредственного её запуска
function start() {
echo | tee -a "${LOGT}"
echo "${DATE}: Procedure is running store is initialized." | tee -a "${LOGT}"
echo | tee -a "${LOGT}"
# Сборка массивов
declare -f start-mdadm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки RAID." | tee -a "${LOGT}"
else
start-mdadm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Assembly arrays failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Активация групп томов LVM
declare -f start-lvm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки LVM." | tee -a "${LOGT}"
else
start-lvm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Activating LVM volume groups failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Создание символической ссылки на заданный раздел целевого диска
declare -f make-symlink >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция создания символической ссылки на раздел целевого диска." | tee -a "${LOGT}"
else
make-symlink
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Create a symbolic link with error. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Монтирование локальных файловых систем хранилища
declare -f start-fs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция монтирования локальных файловых систем хранилища." | tee -a "${LOGT}"
else
start-fs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Mounting file systems store with error. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Публикация файловых систем хранилища посредством NFS
declare -f start-nfs-export >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция публикации файловых систем посредством NFS." | tee -a "${LOGT}"
else
start-nfs-export
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Publication of file systems via NFS storage failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Сборка файловых систем хранилища из ресурсов NFS
declare -f start-nfs-import >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки файловых систем из ресурсов NFS." | tee -a "${LOGT}"
else
# Учитывая то, что нам неизвестно, когда станут доступными все импортируемые ресурсы, закручиваем бесконечный цикл в ожидании полностью безошибочного импорта всех ресурсов
STERR=""
while [ "${STERR}" != "0" ] ; do
# Ждём некоторое время, перед повторением операции (кроме первой итерации)
[ ! -z "${STERR}" ] && sleep 10
start-nfs-import
STERR="${?}"
done
# Проверяем успешность завершения функции импортирования
if [ "${STERR}" -ne "0" ] ; then
echo "${DATE}: The assembly of the storage file system NFS resource failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Сборка файловых систем в единую точку монтирования
declare -f start-mhddfs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция сборки файловых систем в единой точке монтирования." | tee -a "${LOGT}"
else
start-mhddfs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Assembly file systems into a single mount point failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
return ${?}
}
# Определяем функцию остановки хранилища
function stop() {
echo | tee -a "${LOGT}"
echo "${DATE}: Running stop procedure storage." | tee -a "${LOGT}"
echo | tee -a "${LOGT}"
# Разборка файловых систем, смонтированных в единую точку монтирования
declare -f stop-mhddfs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция разборки файловых систем в единой точке монтирования." | tee -a "${LOGT}"
else
stop-mhddfs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Disassembly of file systems mounted in a single mount point failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Разборка файловых систем хранилища из ресурсов NFS
declare -f stop-nfs-import >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция разборки файловых систем из ресурсов NFS." | tee -a "${LOGT}"
else
stop-nfs-import
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Disassembly of the storage file system NFS resource failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Отключение публикации файловых систем хранилища посредством NFS
declare -f stop-nfs-export >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция публикации файловых систем посредством NFS." | tee -a "${LOGT}"
else
stop-nfs-export
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Disabling Publishing file systems via NFS storage failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Демонтирование файловых систем хранилища
declare -f stop-fs >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция демонтирования локальных файловых систем хранилища." | tee -a "${LOGT}"
else
stop-fs
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Unmounting file systems store with error. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Деактивация групп томов LVM
declare -f stop-lvm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция деактивации групп томов LVM хранилища." | tee -a "${LOGT}"
else
stop-lvm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Deactivating LVM volume groups failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Остановка массивов
declare -f stop-mdadm >/dev/null
if [ ${?} -ne 0 ]; then
echo "Notice. Не определена функция деактивации RAID." | tee -a "${LOGT}"
else
stop-mdadm
if [ "${?}" -ne "0" ] ; then
echo "${DATE}: Stop array failed. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
return ${?}
}
# Блок выбора варианта исполнения скрипта
case "$1" in
start)
start-init
# В случае ошибочного завершения сборки хранилища разбираем его
if [ "${?}" -ne "0" ] ; then
stop-init
fi
;;
stop)
stop-init
;;
check)
echo | tee -a "${LOGT}"
echo "${DATE}: Running the test procedure component." | tee -a "${LOGT}"
echo | tee -a "${LOGT}"
check-mdadm
check-lvm
check-fs
check-nfs-export
check-nfs-import
check-mhddfs
;;
*)
echo "Usage $0 {start|stop|check}" >&2
exit 1
;;
esac
exit $?
Прописываем наш скрипт для нужных уровней исполнения в системе:
# update-rc.d storage-control start 10 2 3 4 5 . stop 10 0 1 6 .
Для того, что бы не получать сильно разросшиеся файлы журналов, настроим их ротацию.
Устанавливаем приложение ротации текстовых файлов с одновременным их сжатием:
# aptitude install logrotate gzip
Создаем конфигурационный файл ротации журнальных файлов:
# mkdir -p /etc/logrotate.d
# vi /etc/logrotate.d/storage
# vi /etc/logrotate.d/storage
# шаблон указывающий объекты подлежащие "ротации"
/var/log/storage/*.log {
# размер журнального файла, после которого он обрабатывается утилитой
size 10M
# отсутствие файла не вызывает ошибку
missingok
# количество хранимых отработанных резервных копий
rotate 10
# указание сжимать отрабатываемые резервные копии
compress
# указание не сжимать первую резервную копию, делать это при повторном проходе
delaycompress
# указание не отрабатывать пустые файлы
notifempty
# добавлять к наименованию файла резервной копии даты в формате "-YYYYMMDD"
dateext
# задать права доступа, владельца и группу создаваемого журнального файла
create 640 root root
}
/var/log/storage/*.log {
# размер журнального файла, после которого он обрабатывается утилитой
size 10M
# отсутствие файла не вызывает ошибку
missingok
# количество хранимых отработанных резервных копий
rotate 10
# указание сжимать отрабатываемые резервные копии
compress
# указание не сжимать первую резервную копию, делать это при повторном проходе
delaycompress
# указание не отрабатывать пустые файлы
notifempty
# добавлять к наименованию файла резервной копии даты в формате "-YYYYMMDD"
dateext
# задать права доступа, владельца и группу создаваемого журнального файла
create 640 root root
}
Проверяем корректность конфигурационного файла:
# logrotate -d /etc/logrotate.d/storage
Переход к описанию вспомогательных функций.