Здесь размещено описание одного из функциональных блоков инструкций управления самодельным сетевым хранилищем на сочетании технологий "MDADM + LVM + XFS + NFS + MHDDFS" через простейшие BASH-скрипты. Отдельно неприменимо.
Создадим конфигурационный файл перечнем и описанием характеристик ресурсов, готовых к инициализации и использованию:
# vi /usr/local/etc/storage/cnf.d/fs.cnf
....
hdd.target=hdd0
hdd.target.hdd0.serial=5LJ1J3HB
hdd.target.hdd0.partition=7
hdd.target.hdd0.symlink=sd.sys.xfsjournal
fs.target=storage0
fs.target.storage0.type=xfs
fs.target.storage0.device=/dev/vg0/lvstorage0
fs.target.storage0.mount.journal=/dev/sd.sys.xfsjournal
fs.target.storage0.mount.point=/mnt/storage0
....
hdd.target=hdd0
hdd.target.hdd0.serial=5LJ1J3HB
hdd.target.hdd0.partition=7
hdd.target.hdd0.symlink=sd.sys.xfsjournal
fs.target=storage0
fs.target.storage0.type=xfs
fs.target.storage0.device=/dev/vg0/lvstorage0
fs.target.storage0.mount.journal=/dev/sd.sys.xfsjournal
fs.target.storage0.mount.point=/mnt/storage0
....
Пишем часть функциональности сканирования имеющихся дисковых устройств, поиска среди них наших, проверяющий корректность их применения и создающий для них ссылки, если в этом есть необходимость:
# vi /usr/local/etc/storage/fnc.d/fs.fnc
#!/bin/bash
# This file contains the code snippet for the shell Bash v.4 (Bourne again shell)
# Файл содержит фрагмент кода для командного интерпретатора Bash v.4 (Bourne again shell)
# Функция создания символической ссылки на заданный раздел целевого диска
function make-symlink() {
# Перебираем все строки именований целевых дисков
for HDDS in `grep --ignore-case "^hdd.target=" "${CONF}" | uniq` ; do
HDD=`echo ${HDDS} | awk -F = '{print $2}'`
# Перебираем все строки параметров HDD
for PARAMS in `grep --ignore-case "^hdd.target.${HDD}." "${CONF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".serial=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && SERIAL="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".partition=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && PARTITION="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".symlink=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && SYMLINK="${BUFFER}"
done
if [ "${SERIAL}" == "" ] || [ "${PARTITION}" == "" ] || [ "${SYMLINK}" == "" ] ; then
send-report "Symlink" "Parameters of the target device are not in full. Aborting."
echo "${DATE}: Parameters of the target device are not in full. Aborting." >> "${LOG}"
return 1
fi
# Перебираем все строки именований HDD
for OBJECT in `ls /dev | grep -i "^sd[a-z]$"` ; do
# Ищем совпадения в выводе информации об устройстве с заданным серийным номером
STATE=`hdparm -i /dev/${OBJECT} | grep --ignore-case "serial" | grep --count --ignore-case "${SERIAL}"`
if [ "${STATE}" -ne "0" ] ; then
# Ищем целевой раздел
if [ "`ls /dev | grep --ignore-case ${OBJECT}${PARTITION}`" != "" ] ; then
# Проверяем наличие корректной ссылки
STATE=`ls -l /dev | grep --ignore-case "lrwx" | grep --ignore-case "${SYMLINK}" | grep --count --ignore-case "${OBJECTS}${PART}"`
if [ "${STATE}" -eq "0" ] ; then
ln --force --symbolic /dev/${OBJECT}${PARTITION} /dev/${SYMLINK}
# Проверяем успешность завершения операции
if [ "${?}" -eq "0" ] ; then
echo "${DATE}: A symbolic link ${SYMLINK} successfully created for /dev/${OBJECT}${PARTITION}" >> "${LOG}"
break
else
send-report "Symlink" "Error creating symlink ${SYMLINK}. Aborting."
echo "${DATE}: Error creating symlink ${SYMLINK}. Aborting." >> "${LOG}"
return 1
fi
else
echo "${DATE}: Section on ${PARTITION} of the target device ${OBJECT} is already a symbolic link ${SYMLINK}." >> "${LOG}"
break
fi
else
send-report "Symlink" "The target device ${OBJECT} not specified partition ${PARTITION}. Aborting."
echo "${DATE}: The target device ${OBJECT} not specified partition ${PARTITION}. Aborting" >> "${LOG}"
return 1
fi
fi
done
done
return $?
}
# Функция монтирования вручную подготовленных файловых систем хранилища
function start-fs() {
# Перебираем все строки именований целевых файловых систем
for TFSS in `grep --ignore-case "^fs.target=" "${CONF}" | uniq` ; do
TFS=`echo ${TFSS} | awk -F = '{print $2}'`
# Перебираем все строки параметров целевой файловой системы
for PARAMS in `grep --ignore-case "^fs.target.${TFS}." "${CONF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".type=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSTYPE="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".device=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSDEVICE="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".mount.journal=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSJOURNAL="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".mount.point=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSPOINT="${BUFFER}"
done
if [ "${TFSTYPE}" == "" ] || [ "${TFSDEVICE}" == "" ] || [ "${TFSJOURNAL}" == "" ] || [ "${TFSPOINT}" == "" ] ; then
send-report "FS" "Parameters of the target file system are not fully. Aborting."
echo "${DATE}: Parameters of the target file system are not fully. Aborting." >> "${LOG}"
return 1
fi
# Проверяем доступность целевых блочных устройств
if [ -b "${TFSDEVICE}" ] && [ -b "${TFSJOURNAL}" ] ; then
# Вычленяем из пути к монтируемому блочному устройству его имя
TFSDEVICENAME=`basename "${TFSDEVICE}"`
# Проверяем, не смонтирована ли уже целевая файловая система
STATE=`mount | grep --ignore-case "${TFSDEVICENAME}" | grep --count --ignore-case "${TFSPOINT}"`
if [ "${STATE}" -eq "0" ] ; then
mount -t "${TFSTYPE}" -o noatime,nodiratime,logdev=${TFSJOURNAL} "${TFSDEVICE}" "${TFSPOINT}"
# Проверяем успешность завершения операции
if [ "${?}" -ne "0" ] ; then
send-report "FS" "Error mount target FS ${TFSPOINT}. Aborting."
echo "${DATE}: Error mount target FS ${TFSPOINT}. Aborting." >> "${LOG}"
return 1
fi
# Даём системе пару секунд на осознание места новой файловой системы
sleep 2
# Проверяем успешность отрабатывания операции монтирования файловой системы
STATE=`mount | grep --ignore-case "${TFSDEVICENAME}" | grep --count --ignore-case "${TFSPOINT}"`
if [ "${STATE}" -ne "0" ] ; then
echo "${DATE}: The file system storage successfully installed." >> "${LOG}"
else
send-report "FS" "Mount the file system storage with error. Aborting."
echo "${DATE}: Mount the file system storage with error. Aborting." >> "${LOG}"
return 1
fi
else
echo "${DATE}: The target file system is already mounted to the point ${TFSPOINT}." >> "${LOG}"
fi
else
send-report "FS" "Target block device ${TFSDEVICE} and ${TFSJOURNAL} unavailable. Aborting."
echo "${DATE}: Target block device ${TFSDEVICE} and ${TFSJOURNAL} unavailable. Aborting." >> "${LOG}"
return 1
fi
done
# Создаём файл блокировки, показывающий на состояние работы подсистемы
touch "${LOCK}/fs.lck"
return $?
}
# Функция размонтирования вручную подготовленных файловых систем хранилища
function stop-fs() {
# Перебираем все строки именований целевых файловых систем
for TFSS in `grep --ignore-case "^fs.target=" "${CONF}" | uniq` ; do
TFS=`echo ${TFSS} | awk -F = '{print $2}'`
# Перебираем необходимые строки параметров целевой файловой системы
for PARAMS in `grep --ignore-case "^fs.target.${TFS}." "${CONF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".mount.point=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSPOINT="${BUFFER}"
done
if [ "${TFSPOINT}" == "" ] ; then
send-report "FS" "Parameters of the target file system are not fully. Aborting."
echo "${DATE}: Parameters of the target file system are not fully. Aborting." >> "${LOG}"
return 1
fi
# Проверяем, смонтирована ли уже целевая файловая система
STATE=`mount | grep --count --ignore-case "${TFSPOINT}"`
if [ "${STATE}" -ne "0" ] ; then
umount -f "${TFSPOINT}"
fi
done
# Удаляем файл блокировки, показывающий на состояние работы подсистемы
rm --force "${LOCK}/fs.lck"
return $?
}
# Функция проверки состояния вручную подготовленных файловых систем хранилища
function check-fs() {
# Удостоверимся в том, что монтирование файловых систем хранилища прошло успешно (в противном случае проверку не запускаем - бессмысленно)
if [ -f "${LOCK}/fs.lck" ]; then
echo "check"
fi
return $?
}
# This file contains the code snippet for the shell Bash v.4 (Bourne again shell)
# Файл содержит фрагмент кода для командного интерпретатора Bash v.4 (Bourne again shell)
# Функция создания символической ссылки на заданный раздел целевого диска
function make-symlink() {
# Перебираем все строки именований целевых дисков
for HDDS in `grep --ignore-case "^hdd.target=" "${CONF}" | uniq` ; do
HDD=`echo ${HDDS} | awk -F = '{print $2}'`
# Перебираем все строки параметров HDD
for PARAMS in `grep --ignore-case "^hdd.target.${HDD}." "${CONF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".serial=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && SERIAL="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".partition=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && PARTITION="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".symlink=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && SYMLINK="${BUFFER}"
done
if [ "${SERIAL}" == "" ] || [ "${PARTITION}" == "" ] || [ "${SYMLINK}" == "" ] ; then
send-report "Symlink" "Parameters of the target device are not in full. Aborting."
echo "${DATE}: Parameters of the target device are not in full. Aborting." >> "${LOG}"
return 1
fi
# Перебираем все строки именований HDD
for OBJECT in `ls /dev | grep -i "^sd[a-z]$"` ; do
# Ищем совпадения в выводе информации об устройстве с заданным серийным номером
STATE=`hdparm -i /dev/${OBJECT} | grep --ignore-case "serial" | grep --count --ignore-case "${SERIAL}"`
if [ "${STATE}" -ne "0" ] ; then
# Ищем целевой раздел
if [ "`ls /dev | grep --ignore-case ${OBJECT}${PARTITION}`" != "" ] ; then
# Проверяем наличие корректной ссылки
STATE=`ls -l /dev | grep --ignore-case "lrwx" | grep --ignore-case "${SYMLINK}" | grep --count --ignore-case "${OBJECTS}${PART}"`
if [ "${STATE}" -eq "0" ] ; then
ln --force --symbolic /dev/${OBJECT}${PARTITION} /dev/${SYMLINK}
# Проверяем успешность завершения операции
if [ "${?}" -eq "0" ] ; then
echo "${DATE}: A symbolic link ${SYMLINK} successfully created for /dev/${OBJECT}${PARTITION}" >> "${LOG}"
break
else
send-report "Symlink" "Error creating symlink ${SYMLINK}. Aborting."
echo "${DATE}: Error creating symlink ${SYMLINK}. Aborting." >> "${LOG}"
return 1
fi
else
echo "${DATE}: Section on ${PARTITION} of the target device ${OBJECT} is already a symbolic link ${SYMLINK}." >> "${LOG}"
break
fi
else
send-report "Symlink" "The target device ${OBJECT} not specified partition ${PARTITION}. Aborting."
echo "${DATE}: The target device ${OBJECT} not specified partition ${PARTITION}. Aborting" >> "${LOG}"
return 1
fi
fi
done
done
return $?
}
# Функция монтирования вручную подготовленных файловых систем хранилища
function start-fs() {
# Перебираем все строки именований целевых файловых систем
for TFSS in `grep --ignore-case "^fs.target=" "${CONF}" | uniq` ; do
TFS=`echo ${TFSS} | awk -F = '{print $2}'`
# Перебираем все строки параметров целевой файловой системы
for PARAMS in `grep --ignore-case "^fs.target.${TFS}." "${CONF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".type=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSTYPE="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".device=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSDEVICE="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".mount.journal=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSJOURNAL="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".mount.point=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSPOINT="${BUFFER}"
done
if [ "${TFSTYPE}" == "" ] || [ "${TFSDEVICE}" == "" ] || [ "${TFSJOURNAL}" == "" ] || [ "${TFSPOINT}" == "" ] ; then
send-report "FS" "Parameters of the target file system are not fully. Aborting."
echo "${DATE}: Parameters of the target file system are not fully. Aborting." >> "${LOG}"
return 1
fi
# Проверяем доступность целевых блочных устройств
if [ -b "${TFSDEVICE}" ] && [ -b "${TFSJOURNAL}" ] ; then
# Вычленяем из пути к монтируемому блочному устройству его имя
TFSDEVICENAME=`basename "${TFSDEVICE}"`
# Проверяем, не смонтирована ли уже целевая файловая система
STATE=`mount | grep --ignore-case "${TFSDEVICENAME}" | grep --count --ignore-case "${TFSPOINT}"`
if [ "${STATE}" -eq "0" ] ; then
mount -t "${TFSTYPE}" -o noatime,nodiratime,logdev=${TFSJOURNAL} "${TFSDEVICE}" "${TFSPOINT}"
# Проверяем успешность завершения операции
if [ "${?}" -ne "0" ] ; then
send-report "FS" "Error mount target FS ${TFSPOINT}. Aborting."
echo "${DATE}: Error mount target FS ${TFSPOINT}. Aborting." >> "${LOG}"
return 1
fi
# Даём системе пару секунд на осознание места новой файловой системы
sleep 2
# Проверяем успешность отрабатывания операции монтирования файловой системы
STATE=`mount | grep --ignore-case "${TFSDEVICENAME}" | grep --count --ignore-case "${TFSPOINT}"`
if [ "${STATE}" -ne "0" ] ; then
echo "${DATE}: The file system storage successfully installed." >> "${LOG}"
else
send-report "FS" "Mount the file system storage with error. Aborting."
echo "${DATE}: Mount the file system storage with error. Aborting." >> "${LOG}"
return 1
fi
else
echo "${DATE}: The target file system is already mounted to the point ${TFSPOINT}." >> "${LOG}"
fi
else
send-report "FS" "Target block device ${TFSDEVICE} and ${TFSJOURNAL} unavailable. Aborting."
echo "${DATE}: Target block device ${TFSDEVICE} and ${TFSJOURNAL} unavailable. Aborting." >> "${LOG}"
return 1
fi
done
# Создаём файл блокировки, показывающий на состояние работы подсистемы
touch "${LOCK}/fs.lck"
return $?
}
# Функция размонтирования вручную подготовленных файловых систем хранилища
function stop-fs() {
# Перебираем все строки именований целевых файловых систем
for TFSS in `grep --ignore-case "^fs.target=" "${CONF}" | uniq` ; do
TFS=`echo ${TFSS} | awk -F = '{print $2}'`
# Перебираем необходимые строки параметров целевой файловой системы
for PARAMS in `grep --ignore-case "^fs.target.${TFS}." "${CONF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".mount.point=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && TFSPOINT="${BUFFER}"
done
if [ "${TFSPOINT}" == "" ] ; then
send-report "FS" "Parameters of the target file system are not fully. Aborting."
echo "${DATE}: Parameters of the target file system are not fully. Aborting." >> "${LOG}"
return 1
fi
# Проверяем, смонтирована ли уже целевая файловая система
STATE=`mount | grep --count --ignore-case "${TFSPOINT}"`
if [ "${STATE}" -ne "0" ] ; then
umount -f "${TFSPOINT}"
fi
done
# Удаляем файл блокировки, показывающий на состояние работы подсистемы
rm --force "${LOCK}/fs.lck"
return $?
}
# Функция проверки состояния вручную подготовленных файловых систем хранилища
function check-fs() {
# Удостоверимся в том, что монтирование файловых систем хранилища прошло успешно (в противном случае проверку не запускаем - бессмысленно)
if [ -f "${LOCK}/fs.lck" ]; then
echo "check"
fi
return $?
}
Переход к настройкам публикации и монтирования удалённых NFS-ресурсов.