#!/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= 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 }