|
|
#!/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 $@
|