Здесь размещено описание одного из функциональных блоков инструкций управления самодельным сетевым хранилищем на сочетании технологий "MDADM + LVM + XFS + NFS + MHDDFS" через простейшие BASH-скрипты. Отдельно неприменимо.
Заранее готовим корневую точку монтирования для публикуемых NFS-ресурсов:
# mkdir -p /mnt/export
# chown -R storage:storage /mnt/export
# chmod -R ug+rw /mnt/export
# chown -R storage:storage /mnt/export
# chmod -R ug+rw /mnt/export
Создадим конфигурационный файл перечнем и описанием характеристик ресурсов, готовых к инициализации и использованию:
# vi /usr/local/etc/storage/cnf.d/nfs.export.cnf
....
nfs.export.server.chroot=/mnt/export
nfs.export.server.network=10.10.12.192/28
nfs.export=storage0
nfs.export.storage0.fsid=1
nfs.export.storage0.source=/mnt/storage0
nfs.export.storage0.point=/mnt/export/storage0
nfs.export.storage0.anonuid=1500
nfs.export.storage0.anongid=1500
....
nfs.export.server.chroot=/mnt/export
nfs.export.server.network=10.10.12.192/28
nfs.export=storage0
nfs.export.storage0.fsid=1
nfs.export.storage0.source=/mnt/storage0
nfs.export.storage0.point=/mnt/export/storage0
nfs.export.storage0.anonuid=1500
nfs.export.storage0.anongid=1500
....
Фрагмент кода автоматизации функционала экспорта NFS-ресурсов подсистемы хранения:
# vi /usr/local/etc/storage/fnc.d/nfs.export.fnc
#!/bin/bash
# This file contains the code snippet for the shell Bash v.4 (Bourne again shell)
# Файл содержит фрагмент кода для командного интерпретатора Bash v.4 (Bourne again shell)
# Функция публикации файловых систем хранилища посредством NFS
function start-nfs-export() {
# Вычленяем необходимые глобальные параметры сервера NFS
GECHROOT=`grep --ignore-case "^nfs.export.server.chroot=" "${CNF}" | awk -F = '{print $2}'`
GENETWORK=`grep --ignore-case "^nfs.export.server.network=" "${CNF}" | awk -F = '{print $2}'`
# Проверяем наличие пути к корневой псевдофайловой системе NFS
if [ ! -d "${GECHROOT}" ] ; then
echo "${DATE}: There is no way to root pseudo file system NFS. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем корректность формата NETWORK
if [ "${GENETWORK}" == "" ] ; then
echo "${DATE}: Not all global NFS server settings are in full. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем, не опубликован ли уже корень псевдофайловой системы NFS
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${GECHROOT}[ ]*${GENETWORK}*"`
if [ "${STATE}" -eq "0" ] ; then
exportfs -i -o fsid=0,root_squash ${GENETWORK}:${GECHROOT}
# Проверяем успешность завершения операции
if [ "${?}" != "0" ] ; then
echo "${DATE}: Error export NFS pseudo file system. Aborting." | tee -a "${LOGT}"
return 1
fi
# Даём системе пару секунд на завершение публикации
sleep 2
# Проверяем успешность публикации
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${GECHROOT}[ ]*${GENETWORK}*"`
if [ "${STATE}" -ne "0" ] ; then
echo "${DATE}: NFS resource ${GECHROOT} published successfully." | tee -a "${LOGT}"
else
echo "${DATE}: Publication NFS resource ${GECHROOT} failed. Aborting." | tee -a "${LOGT}"
return 1
fi
else
echo "${DATE}: NFS root pseudo file system has already been published." | tee -a "${LOGT}"
fi
# Перебираем все строки именований публикуемых ресурсов
for ENFSS in `grep --ignore-case "^nfs.export=" "${CNF}" | uniq`; do
ENFS=`echo ${ENFSS} | awk -F = '{print $2}'`
# Перебираем все строки параметров публикуемых ресурсов
for PARAMS in `grep --ignore-case "^nfs.export.${ENFS}." "${CNF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".fsid=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EFSID="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".source=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && ESOURCE="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".point=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EPOINT="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".anonuid=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EANONUID="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".anongid=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EANONGID="${BUFFER}"
done
# Проверяем наличие субьектов файловой системы
if [ ! -d "${ESOURCE}" ] || [ ! -d "${EPOINT}" ] ; then
echo "${DATE}: Not all mounted and exported resources are in full. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем корректность параметров
if [ "${EFSID}" == "" ] || [ "${EANONUID}" == "" ] || [ "${EANONGID}" == "" ] ; then
echo "${DATE}: Not all resource settings are in full. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем, не опубликованы ли уже ресурсы
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${EPOINT}[ ]*${GENETWORK}"`
if [ "${STATE}" -eq "0" ] ; then
# Проверяем, не смонтирован ли уже публикуемый ресурс в псевдофайловую систему NFS
STATE=`mount | grep --count --ignore-case "^${ESOURCE}[ ]*on[ ]*${EPOINT}"`
if [ "${STATE}" -eq "0" ] ; then
# Монтируем публикуемый ресурс
mount --bind "${ESOURCE}" "${EPOINT}"
# Проверяем успешность завершения операции
if [ "${?}" != "0" ] ; then
echo "${DATE}: Error bind mount ${ESOURCE} on ${EPOINT}. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Публикуем целевой ресурс
EOPT="fsid=${EFSID},rw,nohide,all_squash,anonuid=${EANONUID},anongid=${EANONGID},no_subtree_check,sync"
exportfs -i -o ${EOPT} ${GENETWORK}:${EPOINT}
# Проверяем успешность завершения операции
if [ "${?}" != "0" ] ; then
echo "${DATE}: Error export NFS resource ${EPOINT}. Aborting." | tee -a "${LOGT}"
return 1
fi
# Даём системе пару секунд на завершение публикации
sleep 2
# Проверяем успешность публикации целевого ресурса
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${EPOINT}[ ]*${GENETWORK}"`
if [ "${STATE}" -ne "0" ] ; then
echo "${DATE}: NFS resource ${EPOINT} published successfully." | tee -a "${LOGT}"
else
echo "${DATE}: Publication NFS resource ${EPOINT} failed. Aborting." | tee -a "${LOGT}"
return 1
fi
else
echo "${DATE}: Resource ${EPOINT} has already been published." | tee -a "${LOGT}"
fi
done
# Создаём файл блокировки, показывающий на состояние работы подсистемы
touch "${LOCK}/nfs-export.lck"
return $?
}
# Функция прекращения публикации файловых систем хранилища посредством NFS
function stop-nfs-export() {
# Вычленяем необходимые параметры
GECHROOT=`grep --ignore-case "^nfs.export.server.chroot=" "${CNF}" | awk -F = '{print $2}'`
GENETWORK=`grep --ignore-case "^nfs.export.server.network=" "${CNF}" | awk -F = '{print $2}'`
# Перебираем все строки именований публикуемых ресурсов
for ENFSS in `grep --ignore-case "^nfs.export=" "${CNF}" | uniq`; do
ENFS=`echo ${ENFSS} | awk -F = '{print $2}'`
# Вычленяем необходимые параметры публикуемых ресурсов
for PARAMS in `grep --ignore-case "^nfs.export.${ENFS}.point=" "${CNF}" | uniq` ; do
EPOINT=`echo ${PARAMS} | awk -F = '{print $2}'`
# Проверяем состояние публикации целевого ресурса
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${EPOINT}[ ]*${GENETWORK}"`
if [ "${STATE}" -ne "0" ] ; then
# Останавливаем публикацию ресурса
exportfs -u ${GENETWORK}:${EPOINT}
fi
done
done
# Останавливаем публикацию псевдофайловой системы NFS
exportfs -u ${GENETWORK}:${GECHROOT}
# Удаляем файл блокировки, показывающий на состояние работы подсистемы
rm --force "${LOCK}/nfs-export.lck"
return $?
}
# Функция проверки состояния публикации файловых систем хранилища посредством NFS
function check-nfs-export() {
# Удостоверимся в том, что публикация ресурсов прошла успешно (в противном случае проверку не запускаем - бессмысленно)
if [ -f "${LOCK}/nfs-export.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)
# Функция публикации файловых систем хранилища посредством NFS
function start-nfs-export() {
# Вычленяем необходимые глобальные параметры сервера NFS
GECHROOT=`grep --ignore-case "^nfs.export.server.chroot=" "${CNF}" | awk -F = '{print $2}'`
GENETWORK=`grep --ignore-case "^nfs.export.server.network=" "${CNF}" | awk -F = '{print $2}'`
# Проверяем наличие пути к корневой псевдофайловой системе NFS
if [ ! -d "${GECHROOT}" ] ; then
echo "${DATE}: There is no way to root pseudo file system NFS. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем корректность формата NETWORK
if [ "${GENETWORK}" == "" ] ; then
echo "${DATE}: Not all global NFS server settings are in full. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем, не опубликован ли уже корень псевдофайловой системы NFS
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${GECHROOT}[ ]*${GENETWORK}*"`
if [ "${STATE}" -eq "0" ] ; then
exportfs -i -o fsid=0,root_squash ${GENETWORK}:${GECHROOT}
# Проверяем успешность завершения операции
if [ "${?}" != "0" ] ; then
echo "${DATE}: Error export NFS pseudo file system. Aborting." | tee -a "${LOGT}"
return 1
fi
# Даём системе пару секунд на завершение публикации
sleep 2
# Проверяем успешность публикации
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${GECHROOT}[ ]*${GENETWORK}*"`
if [ "${STATE}" -ne "0" ] ; then
echo "${DATE}: NFS resource ${GECHROOT} published successfully." | tee -a "${LOGT}"
else
echo "${DATE}: Publication NFS resource ${GECHROOT} failed. Aborting." | tee -a "${LOGT}"
return 1
fi
else
echo "${DATE}: NFS root pseudo file system has already been published." | tee -a "${LOGT}"
fi
# Перебираем все строки именований публикуемых ресурсов
for ENFSS in `grep --ignore-case "^nfs.export=" "${CNF}" | uniq`; do
ENFS=`echo ${ENFSS} | awk -F = '{print $2}'`
# Перебираем все строки параметров публикуемых ресурсов
for PARAMS in `grep --ignore-case "^nfs.export.${ENFS}." "${CNF}" | uniq` ; do
BUFFER=`echo ${PARAMS} | grep --ignore-case ".fsid=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EFSID="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".source=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && ESOURCE="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".point=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EPOINT="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".anonuid=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EANONUID="${BUFFER}"
BUFFER=`echo ${PARAMS} | grep --ignore-case ".anongid=" | awk -F = '{print $2}'`
[ "${BUFFER}" != "" ] && EANONGID="${BUFFER}"
done
# Проверяем наличие субьектов файловой системы
if [ ! -d "${ESOURCE}" ] || [ ! -d "${EPOINT}" ] ; then
echo "${DATE}: Not all mounted and exported resources are in full. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем корректность параметров
if [ "${EFSID}" == "" ] || [ "${EANONUID}" == "" ] || [ "${EANONGID}" == "" ] ; then
echo "${DATE}: Not all resource settings are in full. Aborting." | tee -a "${LOGT}"
return 1
fi
# Проверяем, не опубликованы ли уже ресурсы
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${EPOINT}[ ]*${GENETWORK}"`
if [ "${STATE}" -eq "0" ] ; then
# Проверяем, не смонтирован ли уже публикуемый ресурс в псевдофайловую систему NFS
STATE=`mount | grep --count --ignore-case "^${ESOURCE}[ ]*on[ ]*${EPOINT}"`
if [ "${STATE}" -eq "0" ] ; then
# Монтируем публикуемый ресурс
mount --bind "${ESOURCE}" "${EPOINT}"
# Проверяем успешность завершения операции
if [ "${?}" != "0" ] ; then
echo "${DATE}: Error bind mount ${ESOURCE} on ${EPOINT}. Aborting." | tee -a "${LOGT}"
return 1
fi
fi
# Публикуем целевой ресурс
EOPT="fsid=${EFSID},rw,nohide,all_squash,anonuid=${EANONUID},anongid=${EANONGID},no_subtree_check,sync"
exportfs -i -o ${EOPT} ${GENETWORK}:${EPOINT}
# Проверяем успешность завершения операции
if [ "${?}" != "0" ] ; then
echo "${DATE}: Error export NFS resource ${EPOINT}. Aborting." | tee -a "${LOGT}"
return 1
fi
# Даём системе пару секунд на завершение публикации
sleep 2
# Проверяем успешность публикации целевого ресурса
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${EPOINT}[ ]*${GENETWORK}"`
if [ "${STATE}" -ne "0" ] ; then
echo "${DATE}: NFS resource ${EPOINT} published successfully." | tee -a "${LOGT}"
else
echo "${DATE}: Publication NFS resource ${EPOINT} failed. Aborting." | tee -a "${LOGT}"
return 1
fi
else
echo "${DATE}: Resource ${EPOINT} has already been published." | tee -a "${LOGT}"
fi
done
# Создаём файл блокировки, показывающий на состояние работы подсистемы
touch "${LOCK}/nfs-export.lck"
return $?
}
# Функция прекращения публикации файловых систем хранилища посредством NFS
function stop-nfs-export() {
# Вычленяем необходимые параметры
GECHROOT=`grep --ignore-case "^nfs.export.server.chroot=" "${CNF}" | awk -F = '{print $2}'`
GENETWORK=`grep --ignore-case "^nfs.export.server.network=" "${CNF}" | awk -F = '{print $2}'`
# Перебираем все строки именований публикуемых ресурсов
for ENFSS in `grep --ignore-case "^nfs.export=" "${CNF}" | uniq`; do
ENFS=`echo ${ENFSS} | awk -F = '{print $2}'`
# Вычленяем необходимые параметры публикуемых ресурсов
for PARAMS in `grep --ignore-case "^nfs.export.${ENFS}.point=" "${CNF}" | uniq` ; do
EPOINT=`echo ${PARAMS} | awk -F = '{print $2}'`
# Проверяем состояние публикации целевого ресурса
STATE=`showmount --exports --no-headers | grep --count --ignore-case "^${EPOINT}[ ]*${GENETWORK}"`
if [ "${STATE}" -ne "0" ] ; then
# Останавливаем публикацию ресурса
exportfs -u ${GENETWORK}:${EPOINT}
fi
done
done
# Останавливаем публикацию псевдофайловой системы NFS
exportfs -u ${GENETWORK}:${GECHROOT}
# Удаляем файл блокировки, показывающий на состояние работы подсистемы
rm --force "${LOCK}/nfs-export.lck"
return $?
}
# Функция проверки состояния публикации файловых систем хранилища посредством NFS
function check-nfs-export() {
# Удостоверимся в том, что публикация ресурсов прошла успешно (в противном случае проверку не запускаем - бессмысленно)
if [ -f "${LOCK}/nfs-export.lck" ]; then
echo "check"
fi
return $?
}
Переход к настройке автоматизации импорта и монтирования NFS-ресурсов.