You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ublinux-init/ublinux/rc.post.d/45-disk-quota

243 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/bin/bash
ENABLED=yes
[ "$ENABLED" != "yes" ] && exit 0
DEBUGMODE=no
unset ROOTFS; [[ -d /usr/lib/ublinux ]] || ROOTFS=.
SOURCE=${ROOTFS}/usr/lib/ublinux/functions; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
SOURCE=${ROOTFS}/usr/lib/ublinux/os-config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
debug_mode "$0" "$@"
SYSCONF="${ROOTFS}/${SYSCONF}"
SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
SOURCE=${SYSCONF}/security; [ -f ${SOURCE} ] && . ${SOURCE} 2>/dev/null
#declare -A DISK_QUOTA
#DISK_QUOTA[usrquota:/dev/sdc1]=enable
#DISK_QUOTA[usrquota:/dev/sdc1]=disable
#DISK_QUOTA[usrquota:/dev/sdc1]=user-1,user-2:7M:8M:0:0:86400:86400
#DISK_QUOTA[usrquota:/dev/sdc1]=user-1,user-2:5M:6M:0:0
#DISK_QUOTA[usrquota:/mnt/MyExt4]=user-1,user-2:5M:6M:0:0
#DISK_QUOTA[usrquota:/dev/sdc1]=:0:0:0:0:604800:604800
#DISK_QUOTA[grpquota:/dev/sdc1]=enable
#DISK_QUOTA[grpquota:/dev/sdc1]=users:5M:6M:0:0:604800:604800
#DISK_QUOTA[grpquota:/mnt/MyExt4]=users:5M:6M:0:0:604800:604800
#DISK_QUOTA[prjquota:/tmp/5/dir23]=3,MyPN-3:3M:4M:10:20:3600:3600
#DISK_QUOTA[prjquota:/mnt/MyExt4/test1]=1,PN-1:2M:3M:0:0:3600:3600
#DISK_QUOTA[prjquota:/mnt/MyExt4/test2]=2,PN-2:3M:4M:10:12:3600:3600
#DISK_QUOTA[quota]=disable
#DISK_QUOTA[quota]=enable
## Назначение квот на дисковые ресурсы
## Может принимать входящий параметр:
## exec_disk_quota DISK_QUOTA[usrquota:/dev/sdc1]=user-1,user-2:5M:6M:0:0 DISK_QUOTA[usrquota:/dev/sdc2]=enable
exec_disk_quota(){
## Использовать дисковые квоты на файловые системы
enable_quota(){
# Включить поддержку квоты
## Варианты опций mount для квотирования:
## noquota # Отключить простые квоты на пользователя и группу
## quota # Включить простые квоты на пользователя и группу
## usrquota # Включить простые квоты на пользователя
## grpquota # Включить простые квоты на группу
## prjquota # Включить квоты на проект
## usrjquota=aquota.user # Включить журналируемые квоты на пользователя
## grpjquota=aquota.group # Включить журналируемые квоты на группу
## jqfmt=vfsold # Использовать БД для простых квот V1
## jqfmt=vfsv0 # Выключить журналирование. Использовать БД для журналируемых квот V2
## jqfmt=vfsv1 # Включить журналирование. Использовать БД для журналируемых квот V2
cat /proc/mounts | grep -q "${PATH_DEVICE}.*${ATTR_QUOTA}" && return 0
MOUNT_DISK_ATTR[${PATH_DEVICE}]=${MOUNT_DISK_ATTR[${PATH_DEVICE}]#,*}
if cat /proc/mounts | grep -q "${PATH_DEVICE}"; then
if [[ ${ISFS_EXT234_FEATURES} == no && ! ${PATH_DEVICE} =~ ^/dev/loop* ]] && umount --quiet ${PATH_DEVICE} 2>/dev/null; then
${ROOTFS}/usr/bin/tune2fs -Q ${MOUNT_DISK_ATTR[${PATH_DEVICE}]} ${PATH_DEVICE} && ISFS_EXT234_FEATURES=yes
mount --all
mount -o ${MOUNT_DISK_ATTR[${PATH_DEVICE}]} ${PATH_DEVICE} ${MOUNT_POINT}
rm -f ${MOUNT_POINT}/{aquota.user,aquota.group,quota.user,quota.group}
elif [[ ${ISFS_EXT234_FEATURES} == yes ]]; then
mount -o remount,${ATTR_QUOTA} ${PATH_DEVICE}
[[ ${ATTR_QUOTA} == usrquota ]] && rm -f ${MOUNT_POINT}/{aquota.user,quota.user}
[[ ${ATTR_QUOTA} == grpquota ]] && rm -f ${MOUNT_POINT}/{aquota.group,quota.group}
elif [[ ${ISFS_EXT234_FEATURES} == no && ${ATTR_QUOTA} != prjquota ]]; then
mount -o remount,${ATTR_QUOTA} ${PATH_DEVICE}
#${ROOTFS}/usr/bin/quotaoff -${ARG_CMD} ${PATH_DEVICE} 2>/dev/null
[[ ${ATTR_QUOTA} == @(usrquota|quota) && ! -f ${MOUNT_POINT}/aquota.user ]] && quotacheck -${ARG_CMD}cm ${PATH_DEVICE}
[[ ${ATTR_QUOTA} == grpquota && ! -f ${MOUNT_POINT}/aquota.group ]] && quotacheck -${ARG_CMD}cm ${PATH_DEVICE}
${ROOTFS}/usr/bin/quotacheck -${ARG_CMD} ${PATH_DEVICE}
fi
else
[[ -n ${ISFS_EXT234} && ${ISFS_EXT234_FEATURES} == no ]] && ${ROOTFS}/usr/bin/tune2fs -Q ${MOUNT_DISK_ATTR[${PATH_DEVICE}]} ${PATH_DEVICE} #2>/dev/null
echo "ERROR: Device '${PATH_DEVICE}' not mounted."
fi
[[ -z ${ROOTFS} ]] && ubconfig --target system set config SERVICESSTART+=,systemd-quotacheck \
|| chroot . ubconfig --target system set config SERVICESSTART+=,systemd-quotacheck
}
disable_quota(){
# Отключить поддержку квот
cat /proc/mounts | grep -q "${PATH_DEVICE}.*${ATTR_QUOTA}" || return 0
${ROOTFS}/usr/bin/quotaoff -${ARG_CMD} ${PATH_DEVICE} 2>/dev/null
if [[ ${ATTR_QUOTA} == quota ]]; then
[[ -z ${ROOTFS} ]] && ubconfig --target system set config SERVICESSTART-=,systemd-quotacheck \
|| chroot . ubconfig --target system set config SERVICESSTART-=,systemd-quotacheck
cat /proc/mounts | grep -q "${PATH_DEVICE}.*${ATTR_QUOTA}" && mount -o remount,noquota ${PATH_DEVICE}
fi
}
set_quota(){
# Установить квоту
QUOTA_LIMITS=$(cut -d: -f1,2,3,4 <<< ${ALL_VALUE_QUOTA} | tr : ' ')
QUOTA_GRACE=$(cut -d: -f5,6 <<< ${ALL_VALUE_QUOTA} | tr : ' ')
#${ROOTFS}/usr/bin/quotaoff -${ARG_CMD} ${PATH_DEVICE} #2>/dev/null
[[ -n ${QUOTA_GRACE} ]] && setquota -${ARG_CMD}t ${QUOTA_GRACE} ${MOUNT_POINT}
if [[ ${ATTR_QUOTA} == @(usrquota|grpquota) && -n ${UGP_QUOTA} ]]; then
tr , '\n' <<< ${UGP_QUOTA} | while read SELECT_UG_QUOTA; do
${ROOTFS}/usr/bin/setquota -${ARG_CMD} ${SELECT_UG_QUOTA} ${QUOTA_LIMITS} ${PATH_DEVICE}
done
elif [[ ${ATTR_QUOTA} == prjquota && -n ${UGP_QUOTA} ]]; then
ID_PROJECT=${UGP_QUOTA%%,*}
NAME_PROJECT=${UGP_QUOTA#*,}
[[ ${ID_PROJECT,,} == auto ]] && ID_PROJECT=${RANDOM}
sed "\|^${ID_PROJECT}:.*|d; \|.*:${PATH_PRJ}$|d" -i /etc/projects
echo "${ID_PROJECT}:${PATH_PRJ}" >> /etc/projects
sed "/.*:${ID_PROJECT}$/d" -i /etc/projid
if [[ -n ${NAME_PROJECT} ]]; then
sed "/^${NAME_PROJECT}:.*/d" -i /etc/projid
echo "${NAME_PROJECT}:${ID_PROJECT}" >> /etc/projid
fi
if [[ -n ${ISFS_EXT234} || -n ${ISFS_XFS} || -n ${ISFS_BTRFS} ]]; then
${ROOTFS}/usr/bin/chattr -p ${ID_PROJECT} ${PATH_PRJ}
${ROOTFS}/usr/bin/chattr +P ${PATH_PRJ}
fi
${ROOTFS}/usr/bin/setquota -${ARG_CMD} ${ID_PROJECT} ${QUOTA_LIMITS} ${PATH_DEVICE}
fi
}
clean_quota(){
# Очистить данные квот
#disable_quota
if cat /proc/mounts | grep -q ${PATH_DEVICE}; then
${ROOTFS}/usr/bin/quotaoff -ugP ${PATH_DEVICE} 2>/dev/null
cat /proc/mounts | grep -q "${PATH_DEVICE}.*${ATTR_QUOTA}" && mount -o remount,noquota ${PATH_DEVICE}
rm -f ${MOUNT_POINT}/{aquota.user,aquota.group,quota.user,quota.group}
if [[ ${ISFS_EXT234_FEATURES} == yes ]] && umount --quiet ${PATH_DEVICE} 2>/dev/null; then
${ROOTFS}/usr/bin/tune2fs -Q ^usrquota,^grpquota,^prjquota ${PATH_DEVICE} 2>/dev/null
#${ROOTFS}/usr/bin/tune2fs -Q quota,project ${PATH_DEVICE} 2>/dev/null
mount --all
mount ${PATH_DEVICE} ${MOUNT_POINT}
fi
else
if [[ ${ISFS_EXT234_FEATURES} == yes ]]; then
${ROOTFS}/usr/bin/tune2fs -Q ^quota,^project ${PATH_DEVICE} 2>/dev/null
#${ROOTFS}/usr/bin/tune2fs -Q quota,project ${PATH_DEVICE} 2>/dev/null
fi
fi
}
debug(){
echo "--------------------------"
echo "ATTR_QUOTA=${ATTR_QUOTA}"
echo "UGP_QUOTA=${UGP_QUOTA}"
echo "ALL_VALUE_QUOTA=${ALL_VALUE_QUOTA}"
echo "IDENT_DEVICE=${IDENT_DEVICE}"
echo "PATH_DEVICE_LSBLK=${PATH_DEVICE_LSBLK}"
echo "PATH_DEVICE=${PATH_DEVICE}"
echo "MOUNT_POINT=${MOUNT_POINT}"
echo "PATH_PRJ=${PATH_PRJ}"
echo "ISFS_EXT234=${ISFS_EXT234}"
echo "ISFS_EXT234_FEATURES=${ISFS_EXT234_FEATURES}"
}
# Если заданы входящие параметр имя переменной со значением, то применяются параметры как основной DISK_QUOTA
[[ -n $@ ]] && declare -A DISK_QUOTA && eval $@
if [[ -n ${DISK_QUOTA[@]} ]]; then
local -A MOUNT_DISK_ATTR
KNOW_LSBLK=$("${ROOTFS}"/usr/bin/lsblk --raw --fs --output PATH,FSTYPE,LABEL,PARTLABEL,UUID,PARTUUID,MOUNTPOINT,MOUNTPOINTS --exclude 11,253)
for SELECT_DISK_QUOTA in "${!DISK_QUOTA[@]}"; do
ATTR_QUOTA=${SELECT_DISK_QUOTA%%:*}
IDENT_DEVICE=${SELECT_DISK_QUOTA#*:}
[[ ${IDENT_DEVICE} == quota ]] && continue
if [[ ${ATTR_QUOTA} == @(usrquota|grpquota|quota) && -n ${IDENT_DEVICE} ]]; then
PATH_DEVICE_LSBLK=$(grep "${IDENT_DEVICE}" <<< ${KNOW_LSBLK} | cut -d' ' -f1)
[[ -n ${PATH_DEVICE_LSBLK} ]] && PATH_DEVICE=${PATH_DEVICE_LSBLK} || PATH_DEVICE=${IDENT_DEVICE}
elif [[ ${ATTR_QUOTA} == prjquota && -n ${IDENT_DEVICE} ]]; then
PATH_PRJ=${SELECT_DISK_QUOTA#*:}
[[ -d ${PATH_PRJ} ]] || continue
PATH_DEVICE=$("${ROOTFS}"/usr/bin/findmnt -n -o SOURCE --target ${PATH_PRJ})
[[ -n ${PATH_DEVICE} ]] || PATH_DEVICE=${IDENT_DEVICE}
fi
MOUNT_DISK_ATTR[${PATH_DEVICE}]+=",${ATTR_QUOTA}"
done
for SELECT_DISK_QUOTA in "${!DISK_QUOTA[@]}"; do
local ISFS_EXT234 MOUNT_POINT PATH_PRJ
local ISFS_EXT234_FEATURES # Данные квот храняться в служебных данных файловой системы
ATTR_QUOTA=${SELECT_DISK_QUOTA%%:*}
case ${ATTR_QUOTA} in
quota) ARG_CMD="ugP"; ARG_TUNE2FS=" quota inode:" ;;
usrquota) ARG_CMD="u"; ARG_TUNE2FS="User quota inode:" ;;
grpquota) ARG_CMD="g"; ARG_TUNE2FS="Group quota inode:" ;;
prjquota) ARG_CMD="P"; ARG_TUNE2FS="Project quota inode:" ;;
*) exit 1 ;;
esac
UGP_QUOTA=${DISK_QUOTA[${SELECT_DISK_QUOTA}]%%:*}
ALL_VALUE_QUOTA="${DISK_QUOTA[${SELECT_DISK_QUOTA}]#*:}"
IDENT_DEVICE=${SELECT_DISK_QUOTA#*:}
[[ ${IDENT_DEVICE} == quota ]] && unset IDENT_DEVICE
if [[ ${ATTR_QUOTA} == @(usrquota|grpquota|quota) && -n ${IDENT_DEVICE} ]]; then
KNOW_LSBLK=$("${ROOTFS}"/usr/bin/lsblk --raw --fs --output PATH,FSTYPE,LABEL,PARTLABEL,UUID,PARTUUID,MOUNTPOINT,MOUNTPOINTS --exclude 11,253)
PATH_DEVICE_LSBLK=$(grep "${IDENT_DEVICE}" <<< ${KNOW_LSBLK} | cut -d' ' -f1)
[[ -n ${PATH_DEVICE_LSBLK} ]] && PATH_DEVICE=${PATH_DEVICE_LSBLK} || PATH_DEVICE=${IDENT_DEVICE}
MOUNT_POINT=$(grep "${PATH_DEVICE}" <<< ${KNOW_LSBLK} | cut -d' ' -f7)
elif [[ ${ATTR_QUOTA} == prjquota && -n ${IDENT_DEVICE} ]]; then
PATH_PRJ=${SELECT_DISK_QUOTA#*:}
[[ -d ${PATH_PRJ} ]] || { echo "ERROR: The specified project directory '${PATH_PRJ}' does not exist." && continue; }
KNOW_LSBLK=$("${ROOTFS}"/usr/bin/findmnt -n -o SOURCE,FSTYPE,TARGET --target ${PATH_PRJ} | xargs)
PATH_DEVICE=$("${ROOTFS}"/usr/bin/findmnt -n -o SOURCE --target ${PATH_PRJ})
[[ -n ${PATH_DEVICE} ]] || PATH_DEVICE=${IDENT_DEVICE}
MOUNT_POINT=$("${ROOTFS}"/usr/bin/findmnt -n -o TARGET --target ${PATH_PRJ})
fi
[[ -n ${KNOW_LSBLK} ]] && ISFS_EXT234=$(grep -oE "${PATH_DEVICE} (ext2|ext3|ext4)" <<< ${KNOW_LSBLK}) #"
[[ -n ${KNOW_LSBLK} && -z ${ISFS_EXT234} ]] && ISFS_XFS=$(grep -oE "${PATH_DEVICE} xfs" <<< ${KNOW_LSBLK})
# Проверить ФС на поддержку SW|HW режимов квот
[[ -n ${ISFS_EXT234} ]] && { ${ROOTFS}/usr/bin/tune2fs -l ${PATH_DEVICE} | grep -q "${ARG_TUNE2FS}" && ISFS_EXT234_FEATURES=yes || ISFS_EXT234_FEATURES=no; }
# TODO: Уточнить получение атрибутов у ФС XFS
[[ -n ${ISFS_XFS} ]] && { ${ROOTFS}/usr/bin/tune2fs -l ${PATH_DEVICE} | grep -q "${ARG_TUNE2FS}" && ISFS_XFS_FEATURES=yes || ISFS_XFS_FEATURES=no; }
#debug
if [[ ${UGP_QUOTA,,} == enable ]]; then
if [[ -n ${PATH_DEVICE} ]]; then
enable_quota
${ROOTFS}/usr/bin/quotaon -${ARG_CMD}vp ${PATH_DEVICE} | grep -qi 'is on (enforced)' || ${ROOTFS}/usr/bin/quotaon -${ARG_CMD} ${PATH_DEVICE}
else
${ROOTFS}/usr/bin/quotaoff -augP 2>/dev/null
${ROOTFS}/usr/bin/quotacheck -aug 2>/dev/null
${ROOTFS}/usr/bin/quotaon -augP 2>/dev/null
#${ROOTFS}/usr/bin/ubconfig set config SERVICESSTART+=,quotaon.service
fi
elif [[ ${UGP_QUOTA,,} == disable ]]; then
if [[ -n ${PATH_DEVICE} ]]; then
disable_quota
else
disable_quota
${ROOTFS}/usr/bin/quotaoff -augP 2>/dev/null
#${ROOTFS}/usr/bin/ubconfig set config SERVICESSTART-=,quotaon.service
fi
elif [[ ${UGP_QUOTA,,} == clean ]]; then
[[ -n ${PATH_DEVICE} ]] && clean_quota
elif [[ ${ALL_VALUE_QUOTA} =~ .*:.*:.*:.* ]]; then
if [[ -n ${PATH_DEVICE} ]]; then
enable_quota
[[ ${ATTR_QUOTA} == prjquota && ${ISFS_EXT234_FEATURES} == no ]] && { echo "ERROR: Project '${UGP_QUOTA}' quota feature not enabled. Cannot enable project quota enforcement." && continue; }
[[ ${ATTR_QUOTA} == prjquota && ${ISFS_XFS_FEATURES} == no ]] && { echo "ERROR: Project '${UGP_QUOTA}' quota feature not enabled. Cannot enable project quota enforcement." && continue; }
if [[ -n ${MOUNT_POINT} ]]; then
set_quota
${ROOTFS}/usr/bin/quotaon -${ARG_CMD}vp ${PATH_DEVICE} | grep -qi 'is on (enforced)' || ${ROOTFS}/usr/bin/quotaon -${ARG_CMD} ${PATH_DEVICE} 2>/dev/null || echo "ERROR: Quota '${ATTR_QUOTA}' not enabled on device '${PATH_DEVICE}'"
fi
fi
fi
done
fi
}
################
##### MAIN #####
################
exec_disk_quota $@