320 lines
8.7 KiB
Bash
320 lines
8.7 KiB
Bash
#!/usr/bin/bash
|
|
|
|
# vim:ft=sh:fdm=marker:fmr={,}
|
|
|
|
# archlabs installer library script file
|
|
# this file is not meant to be run directly
|
|
# sourcing this file in a non bash shell is not advised
|
|
|
|
# shellcheck disable=2154,2034
|
|
|
|
declare -g LVM=""
|
|
declare -g GROUP_PARTS=""
|
|
declare -g VOL_GROUP_MB=0
|
|
|
|
lvm_menu()
|
|
{
|
|
lvm_detect
|
|
tput civis
|
|
|
|
local choice
|
|
choice="$(menubox "$_PrepLVM" "$_LvmMenu" 0 0 0 \
|
|
"$_LvmCreateVG" "vgcreate -f, lvcreate -L -n" \
|
|
"$_LvmDelVG" "vgremove -f" \
|
|
"$_LvMDelAll" "lvrmeove, vgremove, pvremove -f" \
|
|
"$_Back" "-")"
|
|
|
|
case $choice in
|
|
"$_LvmCreateVG")
|
|
lvm_create
|
|
retval=$?
|
|
[[ $retval != 1 ]] && return $retval
|
|
;;
|
|
"$_LvmDelVG") lvm_del_vg ;;
|
|
"$_LvMDelAll") lvm_del_all ;;
|
|
*) return 0
|
|
esac
|
|
|
|
lvm_menu
|
|
}
|
|
|
|
lvm_detect()
|
|
{
|
|
PHYSICAL_VOLUMES="$(pvs -o pv_name --noheading 2>/dev/null)"
|
|
VOLUME_GROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
|
|
VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
|
|
|
|
if [[ $VOLUMES && $VOLUME_GROUP && $PHYSICAL_VOLUMES ]]; then
|
|
infobox "$_PrepLVM" "$_LvmDetBody" 0
|
|
|
|
modprobe dm-mod 2>$ERR
|
|
echeck 'modprobe dm-mod'
|
|
|
|
vgscan >/dev/null 2>&1
|
|
vgchange -ay >/dev/null 2>&1
|
|
fi
|
|
}
|
|
|
|
lvm_show_vg()
|
|
{
|
|
DEL_VG=""
|
|
VOL_GROUP_LIST=""
|
|
|
|
for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
|
|
VOL_GROUP_LIST="$VOL_GROUP_LIST $i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}')"
|
|
done
|
|
|
|
if [[ $VOL_GROUP_LIST == "" ]]; then
|
|
msgbox "$_ErrTitle" "$_LvmVGErr"
|
|
return 1
|
|
fi
|
|
|
|
tput civis
|
|
if ! DEL_VG="$(menubox "$_PrepLVM" "$_LvmSelVGBody" 18 70 10 $VOL_GROUP_LIST)"; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
get_lv_size()
|
|
{
|
|
tput cnorm
|
|
local ttl=" $_LvmCreateVG (LV:$VOL_COUNT) "
|
|
local msg="${VOLUME_GROUP}: ${GROUP_SIZE}$GROUP_SIZE_TYPE (${VOL_GROUP_MB}MB $_LvmLvSizeBody1).$_LvmLvSizeBody2"
|
|
if ! VOLUME_SIZE="$(getinput "$ttl" "$msg" "")"; then
|
|
return 1
|
|
fi
|
|
|
|
ERR_SIZE=0
|
|
# if the size is empty or 0
|
|
(( ${#VOLUME_SIZE} == 0 || ${VOLUME_SIZE:0:1} == 0 )) && ERR_SIZE=1
|
|
|
|
if (( ERR_SIZE == 0 )); then
|
|
# number of characters in VOLUME_SIZE minus the last, which should be a letter
|
|
local lv="$((${#VOLUME_SIZE} - 1))"
|
|
|
|
# loop each character (except the last) in VOLUME_SIZE and ensure they are numbers
|
|
for (( i=0; i<lv; i++ )); do
|
|
[[ ${VOLUME_SIZE:$i:1} != [0-9] ]] && { ERR_SIZE=1; break; }
|
|
done
|
|
|
|
if (( ERR_SIZE == 0 )); then
|
|
# ensure the last character is either m/M or g/G
|
|
case ${VOLUME_SIZE:$lv:1} in
|
|
[mMgG]) ERR_SIZE=0 ;;
|
|
*) ERR_SIZE=1
|
|
esac
|
|
|
|
if (( ERR_SIZE == 0 )); then
|
|
local s=${VOLUME_SIZE:0:$lv}
|
|
local m=$((s * 1000))
|
|
# check whether the value is greater than or equal to the LV remaining Size.
|
|
# if not, convert into MB for VG space remaining.
|
|
case ${VOLUME_SIZE:$lv:1} in
|
|
[Gg])
|
|
if (( m >= VOL_GROUP_MB )); then
|
|
ERR_SIZE=1
|
|
else
|
|
VOL_GROUP_MB=$((VOL_GROUP_MB - m))
|
|
fi
|
|
;;
|
|
[Mm])
|
|
if (( ${VOLUME_SIZE:0:$lv} >= VOL_GROUP_MB )); then
|
|
ERR_SIZE=1
|
|
else
|
|
VOL_GROUP_MB=$((VOL_GROUP_MB - s))
|
|
fi
|
|
;;
|
|
*)
|
|
ERR_SIZE=1
|
|
esac
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if (( ERR_SIZE == 1 )); then
|
|
msgbox "$_ErrTitle" "$_LvmLvSizeErrBody"
|
|
get_lv_size || return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
lvm_volume_name()
|
|
{
|
|
local msg="$1"
|
|
|
|
local default="volmain"
|
|
(( VOL_COUNT > 1 )) && default="volextra"
|
|
|
|
tput cnorm
|
|
local name
|
|
if ! name="$(getinput "$_LvmCreateVG (LV:$VOL_COUNT)" "$msg" "$default")"; then
|
|
return 1
|
|
fi
|
|
|
|
# bad volume name answer or name already in use
|
|
if [[ ${name:0:1} == "/" || ${#name} -eq 0 || $name =~ \ |\' ]] || grep -q "$name" <<< "$(lsblk)"; then
|
|
msgbox "$_ErrTitle" "$_LvmLvNameErrBody"
|
|
lvm_volume_name "$msg" || return 1
|
|
fi
|
|
|
|
VOLUME_NAME="$name"
|
|
return 0
|
|
}
|
|
|
|
lvm_group_name()
|
|
{
|
|
tput cnorm
|
|
local group
|
|
if ! group="$(getinput "$_LvmCreateVG" "$_LvmNameVgBody" "VolGroup")"; then
|
|
return 1
|
|
fi
|
|
|
|
# bad answer or group name already taken
|
|
if [[ ${group:0:1} == "/" || ${#group} -eq 0 || $group =~ \ |\' ]] || grep -q "$group" <<< "$(lsblk)"; then
|
|
msgbox "$_ErrTitle" "$_LvmNameVgErr"
|
|
lvm_group_name || return 1
|
|
fi
|
|
|
|
VOLUME_GROUP="$group"
|
|
return 0
|
|
}
|
|
|
|
lvm_extra_lvs()
|
|
{
|
|
while (( VOL_COUNT > 1 )); do
|
|
# get the name and size
|
|
lvm_volume_name "$_LvmLvNameBody1" || { break; return 1; }
|
|
get_lv_size || { break; return 1; }
|
|
|
|
# create it
|
|
lvcreate -L "$VOLUME_SIZE" "$VOLUME_GROUP" -n "$VOLUME_NAME" 2>$ERR
|
|
echeck "lvcreate -L $VOLUME_SIZE $VOLUME_GROUP -n $VOLUME_NAME"
|
|
msgbox "$_LvmCreateVG (LV:$VOL_COUNT)" "$_Done LV $VOLUME_NAME ($VOLUME_SIZE) $_LvmPvDoneBody2."
|
|
|
|
((VOL_COUNT--)) # decrement the number of volumes chosen after each loop
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
lvm_volume_count()
|
|
{
|
|
if ! VOL_COUNT=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_LvmCreateVG " \
|
|
--radiolist "$_LvmLvNumBody1 $VOLUME_GROUP\n$_LvmLvNumBody2" 0 0 0 \
|
|
"1" "-" off "2" "-" off "3" "-" off "4" "-" off "5" "-" off \
|
|
"6" "-" off "7" "-" off "8" "-" off "9" "-" off); then
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
lvm_partitions()
|
|
{
|
|
find_partitions 'part|crypt' || return 1
|
|
PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
|
|
|
|
# choose partitions
|
|
tput civis
|
|
if ! GROUP_PARTS="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_LvmCreateVG " --checklist "$_LvmPvSelBody" 0 0 0 $PARTS)"; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
lvm_create_group()
|
|
{
|
|
# get volume group name
|
|
lvm_group_name || return 1
|
|
|
|
# loop while setup is not confirmed by the user
|
|
while ! yesno "$_LvmCreateVG" "$_LvmPvConfBody1 $VOLUME_GROUP\n\n$_LvmPvConfBody2 $GROUP_PARTS\n"; do
|
|
lvm_partitions || { break; return 1; }
|
|
lvm_group_name || { break; return 1; }
|
|
done
|
|
|
|
# create it
|
|
vgcreate -f "$VOLUME_GROUP" "$GROUP_PARTS" >/dev/null 2>$ERR
|
|
echeck "vgcreate -f $VOLUME_GROUP $GROUP_PARTS"
|
|
|
|
GROUP_SIZE=$(vgdisplay "$VOLUME_GROUP" | awk '/VG Size/ {
|
|
gsub(/[^0-9.]/, "")
|
|
print int($0)
|
|
}')
|
|
|
|
GROUP_SIZE_TYPE="$(vgdisplay "$VOLUME_GROUP" | awk '/VG Size/ {
|
|
print substr($NF, 0, 1)
|
|
}')"
|
|
|
|
if [[ $GROUP_SIZE_TYPE == 'G' ]]; then
|
|
VOL_GROUP_MB=$((GROUP_SIZE * 1000))
|
|
else
|
|
VOL_GROUP_MB=$GROUP_SIZE
|
|
fi
|
|
|
|
# finished volume group creation
|
|
local msg="$_LvmPvDoneBody1 $VOLUME_GROUP ($GROUP_SIZE $GROUP_SIZE_TYPE)"
|
|
msgbox "$_LvmCreateVG" "$msg $_LvmPvDoneBody2\n"
|
|
return 0
|
|
}
|
|
|
|
lvm_create()
|
|
{
|
|
VOLUME_GROUP=""
|
|
GROUP_PARTS=""
|
|
VOL_GROUP_MB=0
|
|
umount_dir $MNT
|
|
|
|
if [[ $LUKS && $LUKS_NAME ]]; then
|
|
GROUP_PARTS="/dev/mapper/$LUKS_NAME"
|
|
infobox "$_LvmCreateVG" "\nUsing encrypted partition created earlier: $GROUP_PARTS\n" 1
|
|
else
|
|
lvm_partitions || return 1
|
|
fi
|
|
|
|
lvm_create_group || return 1 # create the volume group we'll be using
|
|
lvm_volume_count || return 1 # how many logical volumes to create on the group
|
|
lvm_extra_lvs || return 1 # if we chose more than one logical volume create all but the last
|
|
|
|
# last or only logical volume
|
|
lvm_volume_name "$_LvmLvNameBody1 $_LvmLvNameBody2 (${VOL_GROUP_MB}MB)" || return 1
|
|
lvcreate -l +100%FREE "$VOLUME_GROUP" -n "$VOLUME_NAME" 2>$ERR
|
|
echeck "lvcreate -l +100%FREE $VOLUME_GROUP -n $VOLUME_NAME"
|
|
|
|
LVM=' logical volume'
|
|
show_devices
|
|
return 0
|
|
}
|
|
|
|
lvm_del_vg()
|
|
{
|
|
if lvm_show_vg; then
|
|
yesno "$_LvmDelVG" "$_LvmDelQ" && vgremove -f "$DEL_VG" >/dev/null 2>&1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
lvm_del_all()
|
|
{
|
|
PHYSICAL_VOLUMES="$(pvs -o pv_name --noheading 2>/dev/null)"
|
|
VOLUME_GROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
|
|
VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
|
|
|
|
if yesno "$_LvMDelAll" "$_LvmDelQ"; then
|
|
for i in $VOLUMES; do
|
|
lvremove -f "/dev/mapper/$i" >/dev/null 2>&1
|
|
done
|
|
for i in $VOLUME_GROUP; do
|
|
vgremove -f "$i" >/dev/null 2>&1
|
|
done
|
|
for i in $PHYSICAL_VOLUMES; do
|
|
pvremove -f "$i" >/dev/null 2>&1
|
|
done
|
|
LVM=' logical volume'
|
|
fi
|
|
|
|
return 0
|
|
}
|