#!/bin/bash
#
# To automate the partitioning, set OVIRT_VOL_* in /etc/default/ovirt and call
# ovirt-config-storage AUTO
#
# All sizes are in megabytes
#

. /usr/libexec/ovirt-functions

ME=$(basename "$0")
warn() { printf '%s: %s\n' "$ME" "$*" >&2; }
die() { warn "$*"; exit 1; }

trap '__st=$?; stop_log; exit $__st' 0
trap 'exit $?' 1 2 13 15

# check that we're not booted from local storage; if so then exit with an error
if is_booted_from_local_disk; then
    die "You cannot configure storage on a running system. Please boot from CD/USB to configure storage."
fi

default_overcommit=0.5
default_boot_size=50
default_root_size=256
default_config_size=5
default_logging_size=2048
# -1 indicates data partition should use remaining disk
default_data_size=-1
default_swap2_size=0
default_data2_size=0
boot_min_size=50
root_min_size=256
config_min_size=5
logging_min_size=5
data_min_size=5
swap_min_size=5
default_efi_size=256

# return sd name for given #:# identifier
get_sd_name() {
    local id="$1"
    local device_sys=$(grep -H "^$id$" /sys/block/*/dev | cut -d: -f1)

    if [ -n "$device_sys" ]; then
        echo $(basename $(dirname "$device_sys"))
        return 0
    fi
    return 1
}

# gets the dependent block devices for multipath devices
get_multipath_deps() {
    local mpath_device="$(basename "$1")"
    local deplist_var="$2"
    local deplist=""

    if [[ ! "$1" =~ '/dev/mapper' ]]; then
        evel $deplist_var=$(basename $1)
        return
    fi
    #get dependencies for multipath device
    local deps=$(dmsetup deps -u "mpath-$mpath_device" \
    | sed -r 's/\(([0-9]+), ([0-9]+)\)/\1:\2/g' \
    | sed 's/ /\n/g' | grep [0-9]:[0-9] )

    for dep in $deps
    do
        local device="$(get_sd_name "$dep")"
        if [ -n "$device" ]; then
            if [ -z "$deplist" ]; then
                deplist="$device"
            else
                deplist="$deplist $device"
            fi
        fi
    done

    eval $deplist_var='$deplist'
}

get_drive_size()
{
    local drive="$1"
    local space_var="$2"

    local size=$(sfdisk -s "$drive" 2>/dev/null)
    size=$(echo "scale=0; $size / 1024" | bc -l)

    echo "$drive ($size MB)"
    if [ -n "$space_var" ]; then
        eval $space_var="$size"
    fi
}

check_partition_sizes()
{
    local disk_size need_size

    local min_data_size="$DATA_SIZE"
    if [ "$DATA_SIZE" = -1 ]; then
        min_data_size=5
    fi
    local min_data2_size="$DATA2_SIZE"
    if [ "$DATA2_SIZE" = -1 ]; then
        min_data2_size=5
    fi

    printf "\n"
    if [ "$OVIRT_ISCSI_ENABLED" = "y" ]; then
        get_drive_size "$BOOTDRIVE" BOOTDRIVESPACE
        drive_list="BOOT"
        BOOT_NEED_SIZE="$BOOT_SIZE"
    else
        get_drive_size "$ROOTDRIVE" ROOTDRIVESPACE
        oldIFS="$IFS"
        IFS="$SEP"
        for drv in $HOSTVGDRIVE; do
            get_drive_size "$drv" DRIVESPACE
            if [ -n "${HOSTVGDRIVESPACE}" ]; then
                HOSTVGDRIVESPACE=$(echo "scale=0;" \
                                 "$HOSTVGDRIVESPACE + $DRIVESPACE" | bc -l)
            else
                HOSTVGDRIVESPACE=$DRIVESPACE
            fi
        done
        if [ -n "${APPVGDRIVE}" ]; then
            for drv in $APPVGDRIVE; do
                get_drive_size "$drv" DRIVESPACE
                if [ -n "${APPVGDRIVESPACE}" ]; then
                    APPVGDRIVESPACE=$(echo "scale=0;" \
                                     "$APPVGDRIVESPACE + $DRIVESPACE" | bc -l)
                else
                    APPVGDRIVESPACE=$DRIVESPACE
                fi
            done
            APPVG_NEED_SIZE=$(echo "scale=0; $SWAP2_SIZE + $min_data2_size" | bc -l)
        fi
        IFS="$oldIFS"
        ROOT_NEED_SIZE=$(echo "scale=0; $ROOT_SIZE * 2 + $EFI_SIZE"| bc -l)
        HOSTVG_NEED_SIZE=$(echo "scale=0;" \
                         "$SWAP_SIZE + $CONFIG_SIZE + $LOGGING_SIZE + $min_data_size" | bc -l)

        if [ "$ROOTDRIVE" = "$HOSTVGDRIVE" ]; then
            drive_list="ROOT"
            ROOT_NEED_SIZE=$(echo "scale=0; $ROOT_SIZE * 2 + $HOSTVG_NEED_SIZE"| bc -l)
        else
            drive_list="ROOT HOSTVG"
            oldIFS="$IFS"
            IFS="$SEP"
            for drv in $HOSTVGDRIVE; do
                # XXX first in hostvgdrive list is assumed to be rootdrive
                if [ "$ROOTDRIVE" = "$drv" ]; then
                    HOSTVGDRIVESPACE=$(echo "scale=0; $HOSTVGDRIVESPACE - $ROOT_NEED_SIZE"| bc -l)
                fi
                break
            done
            IFS="$oldIFS"
        fi
        if [ -n "${APPVGDRIVE}" ]; then
            drive_list="${drive_list} APPVG"
        fi
    fi

    for drive in $drive_list; do
        drive_need_size=$(eval "echo \${$(echo ${drive}_NEED_SIZE)"})
        drive_disk_size=$(eval "echo \${$(echo ${drive}DRIVESPACE)"})

        if [ $drive_need_size -gt $drive_disk_size ]; then
            local gap_size=$(echo "scale=0; $drive_need_size-$drive_disk_size;" | bc -l)
            printf "\n"
            printf "=============================================================\n"
            printf "The target storage device is too small for the desired sizes:\n"
            printf " Disk Target: $drive \n"
            printf " Size of target storage device: $drive_disk_size MB\n"
            printf " Total storage size to be used: $drive_need_size MB\n"
            printf "\n"
            printf "You need an additional $gap_size MB of storage.\n"
            printf "\n"
            return 1
        else
            printf "Required Space : $drive_need_size MB\n\n"
        fi
    done
}

manual_input()
{
    local manual_device
    local return_var="$1"
    while true; do
        read -rp "Enter disk device path: " manual_device
        if [ -z "$manual_device" ]; then
            return 1
        fi
        manual_device="$(translate_multipath_device "$manual_device")"
        if [ -n "$manual_device" ]; then
            if [ -b "$(readlink -f "$manual_device")" ]; then
                eval $return_var="$manual_device"
                return 0
            fi
        else
            return 1
        fi
    done
}

# Find a usable/selected storage device.
# If there are none, give a diagnostic and return nonzero.
# If there is just one, e.g., /dev/sda, treat it as selected (see below).
# and return 0.  If there are two or more, make the user select one
# or decline.  Upon decline, return nonzero. Otherwise, print the
# selected name, then return 0.
# Sample output: /dev/sda
get_dev_name()
{
    local devices=""
    # list separator
    for d in $(ls -db /sys/block/[hsv]d*); do
        devices="/dev/$(basename "$d")${LF}${devices}"
    done

    local byid_list=$(find /dev/disk/by-id -mindepth 1 -not -name '*-part*' 2>/dev/null)
    for d in $byid_list; do
        local devicename="$(readlink -f "$d")"
        if udevadm info --name="$(basename "$devicename")" --query=property | grep -q ^ID_BUS; then
            devices="${devicename}${LF}${devices}"
        fi
    done

    # FIXME: workaround for detecting cciss devices
    for d in $(ls /dev/cciss/ 2>/dev/null); do
        if [[ ! "$d" =~ p[0-9]+\$ ]]; then
            devices="/dev/cciss/$d${LF}${devices}"
        fi
    done

    # include multipath devices
    local devs_to_remove=""
    oldIFS="$IFS"
    IFS="$LF"
    for d in $(dmsetup ls --target=multipath | cut -f1)
    do
        devices="/dev/mapper/$d${LF}${devices}"
        local sd_devs=""
        IFS="$oldIFS" get_multipath_deps "/dev/mapper/$d" sd_devs
        local dm_dev=$(multipath -ll "$d" | grep "$d" | sed -r 's/^.*(dm-[0-9]+ ).*$/\1/' )
        devs_to_remove="${devs_to_remove} ${sd_devs} ${dm_dev} "
        #  example: ++ devs_to_remove=' sda dm-2 '
    done
    # Remove /dev/sd* devices that are part of a multipath device
    local dev_list=""
    for d in $devices
    do
        if [[ ! "$devs_to_remove" =~ "$(basename "$d") " ]]; then
            dev_list="$d${LF}$dev_list"
        fi
    done
    devices=$(echo "$dev_list" | sort -u | grep -v "^$")
    local num_devices=$(echo "$devices" | wc -l)

    # If there's only one device, use it.
    case $num_devices in
        0) warn "ERROR: found no usable block device"; IFS="$oldIFS"; return 1;;
        1) echo "$devices"; IFS="$oldIFS"; return 0;;
        *) ;; # found more than one
    esac

    # There are two or more; make the user choose.
    # display description for each disk
    for d in $devices; do
        get_drive_size "$d" >&2
    done
    local rc=0
    local choices="$devices${LF}Abort${LF}Manual Selection"
    select device in $choices
    do
        test "$device" = Abort && rc=1
        test "$device" = "Manual Selection" && manual_input device
        test "$device" = "Manual Selection" && rc=1
        test -z "$device" && continue
        test $rc = 0 && echo "$device"
        break
    done
    IFS="$oldIFS"
    return $rc
}

do_configure()
{
    local name_and_size
    if [ "$OVIRT_ISCSI_ENABLED" = "y" ]; then
        printf "\n\nPlease select the disk to use for the Boot partition.\n\n"
        BOOTDRIVE="$(get_dev_name)" || return 0
        get_drive_size "$BOOTDRIVE" BOOTDRIVESPACE
        echo "$BOOTDRIVE"
        OVIRT_ISCSI_HOSTVG="y"
        printf "\n\nPlease select the disk to use for the HostVG.\n\n"
        HOSTVGDRIVE=$(get_dev_name) || return 0
        get_drive_size "$HOSTVGDRIVE" HOSTVGDRIVESPACE
        echo "$HOSTVGDRIVE"
    else
        printf "\n\nPlease select the disk to use for the Root.\n\n"
        ROOTDRIVE=$(get_dev_name) || return 0
        get_drive_size "$ROOTDRIVE" ROOTDRIVESPACE
        if ask_yes_or_no "Will Root be shared with other nodes ([Y]es/[N]o)?"; then
            OVIRT_SHARED_ROOT="y"
            if ask_yes_or_no "Partition and install Root?"; then
                OVIRT_ROOT_INSTALL="y"
            else
                OVIRT_ROOT_INSTALL="n"
            fi
        else
            OVIRT_SHARED_ROOT="n"
            OVIRT_ROOT_INSTALL="y"
        fi

    augtool <<EOF
        set /files$OVIRT_DEFAULTS/OVIRT_SHARED_ROOT $OVIRT_SHARED_ROOT
        set /files$OVIRT_DEFAULTS/OVIRT_ROOT_INSTALL $OVIRT_ROOT_INSTALL
EOF

        printf "\n\nPlease select the disk to use for the HostVG.\n\n"
        while true; do
            HOSTVGDRIVE=$(get_dev_name) || return 0
            if [ "$OVIRT_SHARED_ROOT" = "y" ]; then
                if [ "$ROOTDRIVE" = "$HOSTVGDRIVE" ]; then
                    printf "\n\nRoot Drive and HostVG drive must be different when shared\n\n"
                    return 1
                else
                    break;
                fi
            fi
            break;
        done

        local skipped=false
        if check_existing_hostvg "$HOSTVGDRIVE" devs; then
            oldIFS="$IFS"
            IFS="$SEP"
            for dev in $devs
            do
                printf "Removing HostVG on $dev will erase the drive and cannot be undone\n"
                if ask_yes_or_no "Do you want to remove HostVG from $dev (y/n)?"; then
                    start_log
                    if ! wipe_lvm_on_disk "$dev"; then
                        stop_log
                        IFS="$oldIFS"
                        return 1
                    fi
                    stop_log
                else
                    skipped=true
                fi
            done
            IFS="$oldIFS"
        fi
        $skipped  && printf "Installation cannot proceed with existing HostVG.\n" && return 0
        get_drive_size "$HOSTVGDRIVE" HOSTVGDRIVESPACE
        echo "$HOSTVGDRIVESPACE"
    fi
    printf "\n\nPlease configure storage partitions.\n\n"
    printf "* Enter partition sizes in MB.\n"
    printf "* A value of 0 indicates the partition should be disabled.\n"
    printf "* If the partition is enabled, it will have a minimum valid size.\n"
    printf "* Size remaining value is approximate due to cylinder rounding\n"
    printf "  during partitioning.\n"
    printf "* For the Data partition, a size of -1 indicates that the\n"
    printf "  partition should use up the remaining space on the disk.\n\n"

    if do_review; then
        if ask_yes_or_no "Use these default values ([Y]es/[N]o)?"; then
            return
        fi
    else
        printf "Selected disk is too small for default storage configuration"
    fi

    local space_left=$HOSTVGDRIVESPACE
    if [ "$OVIRT_ISCSI_ENABLED" = "y" -a "$OVIRT_ISCSI_HOSTVG" != "y" ]; then
        partlist=""
        local space_left=$BOOTDRIVESPACE
    elif [ "$OVIRT_ISCSI_ENABLED" = "y" -a "$OVIRT_ISCSI_HOSTVG" = "y" ]; then
        partlist="swap config logging data"
        local space_left=$BOOTDRIVESPACE
    elif [ "$OVIRT_ROOT_INSTALL" = "n" ]; then
        partlist="swap config logging data"
    else
        partlist="swap config logging data"
    fi
    for part in $partlist ; do
        part_regexp="^0$"
        if [ "$part" = "data" ]; then
            part_regexp="^\-1|0$"
        fi
        uc=$(echo $part|tr '[[:lower:]]' '[[:upper:]]')
        size_var=${uc}_SIZE
        eval "size=\$$size_var"
        min_size_var=${part}_min_size
        eval "min_size=\$$min_size_var"

        while true; do
            printf "\n"
            read -ep "Change $part partition size. (Def. ${size}MB), Min. ${min_size}MB, Max. ~${space_left}MB? or Q to quit "
            mb_input=$REPLY
            test -z "$mb_input" && mb_input=$size
            local size_used=0
            if [ $mb_input = "q" -o $mb_input = "Q" ]; then
                printf "Aborting"
                return
            elif [[ $mb_input =~ ^-*[0-9]+$ ]]; then
                if [[ $mb_input -ge $min_size || $mb_input =~ $part_regexp ]] \
                    && [[ $mb_input -le $space_left ]] ; then
                    eval "$size_var=$mb_input"
                    size_used=$mb_input
                    break;
                else
                    printf "invalid $part size: $mb_input.  "
                    printf "Does not fall into specified range.\n"
                fi
            else
                printf "invalid $part size: '$mb_input'.\n"
            fi
        done
        space_left=$(echo "scale=0;$space_left - $size_used" | bc -l)
    done

    if ! check_partition_sizes; then
        printf "Please try partitioning again.\n"
        ROOTDRIVE=
        return 1
    fi

    # save input variables
    augtool <<EOF
set /files$OVIRT_DEFAULTS/OVIRT_VOL_BOOT_SIZE $BOOT_SIZE
set /files$OVIRT_DEFAULTS/OVIRT_VOL_SWAP_SIZE $SWAP_SIZE
set /files$OVIRT_DEFAULTS/OVIRT_VOL_ROOT_SIZE $ROOT_SIZE
set /files$OVIRT_DEFAULTS/OVIRT_VOL_CONFIG_SIZE $CONFIG_SIZE
set /files$OVIRT_DEFAULTS/OVIRT_VOL_LOGGING_SIZE $LOGGING_SIZE
set /files$OVIRT_DEFAULTS/OVIRT_VOL_DATA_SIZE $DATA_SIZE
EOF

   if [ -n "$BOOTDRIVE" ]; then
       augtool <<EOF
set /files$OVIRT_DEFAULTS/OVIRT_INIT_BOOT "$BOOTDRIVE"
EOF
   else
   augtool <<EOF
set /files$OVIRT_DEFAULTS/OVIRT_INIT "$ROOTDRIVE"
EOF
   fi
}

do_review()
{
    if [[ -z "$ROOTDRIVE" && "$OVIRT_ISCSI_ENABLED" != "y" ]]; then
        printf "\nNo Root storage device selected.\n"
        return 1
    fi

    if [[ -z "$HOSTVGDRIVE" ]]; then
        printf "\nNo HostVG storage device selected.\n"
        return 1
    fi
    local is_negative=0

    local data_size_display="$DATA_SIZE MB"
    if [ "$DATA_SIZE" = -1 ]; then

        if [ "$ROOTDRIVE" = "$HOSTVGDRIVE" ]; then
            local remaining_mb=$(( $ROOTDRIVESPACE - $SWAP_SIZE \
                    - $ROOT_SIZE * 2 - $CONFIG_SIZE - $LOGGING_SIZE ))
            test $remaining_mb -lt 0 && is_negative=1
        else
            local remaining_mb=$(( $HOSTVGDRIVESPACE - $SWAP_SIZE - $CONFIG_SIZE - $LOGGING_SIZE ))
            test $remaining_mb -lt 0 && is_negative=1
        fi
        data_size_display="$remaining_mb MB"
    fi

    if [ "$OVIRT_ISCSI_ENABLED" != "y" ]; then
        cat <<EOF

The selected disk will be repartitioned as follows:
================================================
                   Root Drive: $(get_drive_size "$ROOTDRIVE")
                 HostVG Drive: $(get_drive_size "$HOSTVGDRIVE")
          Swap partition size: $SWAP_SIZE MB
  Installation partition size: $ROOT_SIZE * 2 MB
 Configuration partition size: $CONFIG_SIZE MB
       Logging partition size: $LOGGING_SIZE MB
          Data partition size: $data_size_display

EOF
    else
        cat <<EOF

The selected disk will be repartitioned as follows:
================================================
                   Boot Drive: $(get_drive_size "$BOOTDRIVE")
          Boot partition size: $BOOT_SIZE

EOF

    fi
        if [ "$OVIRT_ISCSI_HOSTVG" = "y" ]; then
            cat <<EOF
                HostVG Drive: $(get_drive_size "$HOSTVGDRIVE")
          Swap partition size: $SWAP_SIZE MB
  Installation partition size: $ROOT_SIZE * 2 MB
 Configuration partition size: $CONFIG_SIZE MB
       Logging partition size: $LOGGING_SIZE MB
          Data partition size: $data_size_display
EOF
        fi
    return ${is_negative-0}

}

#Check for an existing VG on any device on the system.
# Return 0 if there is a VG found, unless only one found is on $1
# Return 1 if no VG found or only found on $1
check_existing_hostvg()
{
    local install_dev=
    local dev=
    oldIFS="$IFS"
    IFS="$SEP"
    for dev in $1; do
        if [ -n "${install_dev}" ]; then
            install_dev="${install_dev}+|${dev}"
            # XXX +| => wrong match e.g. sdaa vs sda ?
        else
            install_dev="${dev}"
        fi
    done
    IFS="$oldIFS"
    local devices_var=$2
    local vgname=
    if [ -n "$3" ]; then
        vgname="$3"
    else
        vgname="HostVG"
    fi

    if [ -z "$install_dev" ]; then
        devices="$(pvs --separator="${TAB}" -o pv_name,vg_name --noheadings | \
            grep "${vgname}" | cut -f1)"
    else
        devices="$(pvs --separator="${TAB}" -o pv_name,vg_name --noheadings | \
            egrep -v "${install_dev}" | grep "${vgname}" | cut -f1)"
    fi
    rc=1
    if [ -n "$devices" ]; then
        printf "\n"
        printf "There appears to already be an installation on another device:\n"
        oldIFS="$IFS"
        IFS="$LF"
        for device in $devices; do
            printf "\t$device\n"
        done
        IFS="$oldIFS"
        printf "The installation cannot proceed until the device is removed\n"
        printf "from the system of the HostVG volume group is removed.\n"
        rc=0
    fi

    test -n "$devices_var" && eval "$devices_var"="\"$devices\""

    return $rc
}

# cleanup lvms on selected disk
# - remove mounted filesystems
# - remove LVM volumes and groups
wipe_lvm_on_disk()
{
    local devs=${1-"$HOSTVGDRIVE"}
    local query1=
    local query2=
    unmount_logging
    unmount_config /etc/default/ovirt
#    local part_delim="p"
#    if [[ "$dev" =~ /dev/[hsv]d ]]; then
#        part_delim=""
#    fi
    oldIFS="$IFS"
    IFS="$SEP"
    for d in $devs; do
        local part_delim="p"
        if [[ "$d" =~ "/dev/sd" ]]; then
            part_delim=""
        fi
        if [ -n "${query1}" ]; then
           query1="${query1} ${d} ${d}${part_delim}[0-9]*"
        else
           query1="${d} ${d}${part_delim}[0-9]*"
        fi
        if [ -n "${query2}" ]; then
           query2="${query2}+|${d}${part_delim}[0-9]+|${d}"
        else
           query2="${d}${part_delim}[0-9]+|${d}"
        fi
    done
    IFS="$oldIFS"
    for vg in $(pvs -o vg_uuid --noheadings "$query1" 2>/dev/null|sort -u); do

#    for vg in $(pvs -o vg_uuid --noheadings $dev $dev${part_delim}[0-9]* \
#        --config " devices { filter = [ \"a/.*/\" ] } "  \
#        2>/dev/null|sort -u); do
        if pvs -o pv_name,vg_uuid --noheadings \
            --config " devices { filter = [ \"a/.*/\" ] } " | \
            grep "$vg" | egrep -v -q "${query2} " 2>/dev/null; then

#            grep "$vg" | egrep -v -q "${dev}${part_delim}[0-9]+|${dev} " 2>/dev/null; then
            log "The volume group \"$vg\" spans multiple disks."
            log "This operation cannot complete.  Please manually"
            log "cleanup the storage using standard linux tools."
            return 1
        fi
        vg_name=$(vgs -o vg_name,vg_uuid --noheadings \
            --config " devices { filter = [ \"a|$dev|\", \"r/.*/\" ] } " \
            2>/dev/null | grep -w "$vg" | awk '{print $1}')
        wipe_volume_group "${vg_name}" "$dev"
    done
    return 0
}

reread_partitions()
{
    local drive="$1"
    udevadm settle 2> /dev/null

    if [[ "$drive" =~ "/dev/mapper" ]]; then
        # kpartx -a -p p "$drive"
        # XXX fails with spaces in device names (TBI)
        # ioctl(3, DM_TABLE_LOAD, 0x966980) = -1 EINVAL (Invalid argument)
        # create/reload failed on 0QEMU    QEMU HARDDISK   drive-scsi0-0-0p1

        # flush to sync DM and blockdev, workaround from rhbz#623846#c14
        echo 3 > /proc/sys/vm/drop_caches
        set +e
        until partprobe "$drive"; do
            log "retrying partprobe"
            sleep 1
        done
        set -e
    else
        # ioctl 0x0000125F   BLKRRPART    void
        set +e
        until blockdev --rereadpt "$drive"; do
            log "retrying blockdev"
            sleep 1
        done
        set -e
    fi
}

create_hostvg()
{
    log "Creating LVM partition(s) for HostVG"
    local drv
    local parted_cmd
    oldIFS="$IFS"
    IFS="$SEP"
    local physical_vols=
    for drv in $HOSTVGDRIVE; do
        if [ "$ROOTDRIVE" = "$drv" ]; then
            parted_cmd="mkpart primary ext2 ${RootBackup_end}M -1"
            hostvgpart="4"
        elif [ "$BOOTDRIVE" = "$drv" ]; then
            parted_cmd="mkpart primary ext2 ${boot_size_si} -1"
            hostvgpart="2"
            # FIXME : set for gtpsync/parted compat for now
            ROOTDRIVE=$BOOTDRIVE
        else
            parted_cmd="mkpart primary ext2 2048s -1"
            hostvgpart="1"
        fi
        while true; do
            set +e
            parted -s "$drv" "$parted_cmd"
            parted -s "$drv" "set $hostvgpart lvm on"
            set -e
            reread_partitions "$drv"
            if [ -e "${drv}${hostvgpart}" -o "${drv}p${hostvgpart}" ]; then
                break
            fi
        done

        # sync GPT to the legacy MBR partitions
        if [ "${OVIRT_INSTALL_ROOT}" = "y" ]; then
            if [ "gpt" = "$LABEL_TYPE" ]; then
                log "Running gptsync to create legacy mbr"
                gptsync "$ROOTDRIVE"
            fi
        fi

        partpv="${drv}${hostvgpart}"
        if [ ! -e "$partpv" ]; then
            # e.g. /dev/cciss/c0d0p2 or /dev/mapper/<wwid>p3
            partpv="${drv}p${hostvgpart}"
        fi
        log "Creating physical volume"
        for count in $(seq 1 10); do
            if [ ! -e "$partpv" ]; then
                sleep 1
                if [[ "$count" == "10" && ! -e "$partpv" ]]; then
                    log "$partpv is not available!"
                    exit 1
                fi
            fi
        done
        dd if=/dev/zero of="${partpv}" bs=1024k count=1
        pvcreate -ff -y "${partpv}"
        physical_vols="${physical_vols}${SEP}${partpv}"
    done

    log "Creating volume group HostVG"
    local is_first=1
    for drv in $physical_vols; do
        if [ -z "$drv" ]; then
            continue
        fi
        if [ "$is_first" ]; then
            vgcreate HostVG "$drv"
            is_first=
        else
            vgextend HostVG "$drv"
        fi
    done
    IFS="$oldIFS"

    if [ "$SWAP_SIZE" -gt 0 ]; then
        log "Creating swap partition"
        lvcreate --name Swap --size ${SWAP_SIZE}M /dev/HostVG
        if [ -n "${OVIRT_CRYPT_SWAP}" ]; then
            echo "SWAP /dev/HostVG/Swap /dev/mapper/ovirt-crypt-swap ${OVIRT_CRYPT_SWAP}" >> /etc/ovirt-crypttab
        else
            mkswap -L "SWAP" /dev/HostVG/Swap
            echo "/dev/HostVG/Swap swap swap defaults 0 0" >> /etc/fstab
        fi
    fi
    if [ "$CONFIG_SIZE" -gt 0 ]; then
        log "Creating config partition"
        lvcreate --name Config --size ${CONFIG_SIZE}M /dev/HostVG
        mke2fs -j -t ext4 /dev/HostVG/Config -L "CONFIG"
        tune2fs -c 0 -i 0 /dev/HostVG/Config
    fi
    if [ "$LOGGING_SIZE" -gt 0 ]; then
        log "Creating log partition"
        lvcreate --name Logging --size ${LOGGING_SIZE}M /dev/HostVG
        mke2fs -j -t ext4 /dev/HostVG/Logging -L "LOGGING"
        tune2fs -c 0 -i 0 /dev/HostVG/Logging
        echo "/dev/HostVG/Logging /var/log ext4 defaults,noatime 0 0" >> /etc/fstab
    fi

    local use_data=1
    if [ "$DATA_SIZE" -eq -1 ]; then
        log "Creating data partition with remaining free space"
        lvcreate --name Data -l 100%FREE /dev/HostVG
        use_data=0
    elif [ "$DATA_SIZE" -gt 0 ]; then
        log "Creating data partition"
        lvcreate --name Data --size ${DATA_SIZE}M /dev/HostVG
        use_data=0
    fi

    if [ "$use_data" = 0 ]; then
        mke2fs -j -t ext4 /dev/HostVG/Data -L "DATA"
        tune2fs -c 0 -i 0 /dev/HostVG/Data
        echo "/dev/HostVG/Data /data ext4 defaults,noatime 0 0" >> /etc/fstab
        echo "/data/images /var/lib/libvirt/images bind bind 0 0" >> /etc/fstab
        echo "/data/core /var/log/core bind bind 0 0" >> /etc/fstab
    fi

    # end critical section
    set +x
    set +e

    log "Mounting config partition"
    if mount_config; then
        ovirt_store_config /etc/fstab
    fi

    mount_logging
    if [ "$use_data" = 0 ]; then
        log "Mounting data partition"
        mount_data
    fi
    log "Completed HostVG!"

}

create_appvg()
{
    log "Creating LVM partition(s) for AppVG"
    local drv
    local physical_vols=
    oldIFS="$IFS"
    IFS="$SEP"
    for drv in $APPVGDRIVE; do
        wipe_partitions "$drv"
        reread_partitions "$drv"
        log "Labeling Drive: $drv"
        appvgpart="1"
        while true; do
            set +e
            parted -s "$drv" "mklabel ${LABEL_TYPE} mkpart primary ext2 2048s -1 set $appvgpart lvm on print"
            set -e
            reread_partitions "$drv"
            if [ -e "${drv}${appvgpart}" -o "${drv}p${appvgpart}" ]; then
                break
            fi
        done

        partpv="${drv}${appvgpart}"
        if [ ! -e "$partpv" ]; then
            # e.g. /dev/cciss/c0d0p2
            partpv="${drv}p${appvgpart}"
        fi
        log "Creating physical volume"
        if [ ! -e "$partpv" ]; then
            log "$partpv is not available!"
            exit 1
        fi
        dd if=/dev/zero of="${partpv}" bs=1024k count=1
        pvcreate -ff -y "${partpv}"
        physical_vols="${physical_vols}${SEP}${partpv}"
    done

    log "Creating volume group AppVG"
    local is_first=1
    for drv in $physical_vols; do
        if [ -z "$drv" ]; then
            continue
        fi
        if [ "$is_first" ]; then
            vgcreate AppVG "$drv"
            is_first=
        else
            vgextend AppVG "$drv"
        fi
    done
    IFS="$oldIFS"

    if [ "$SWAP2_SIZE" -gt 0 ]; then
        log "Creating swap2 partition"
        lvcreate --name Swap2 --size ${SWAP2_SIZE}M /dev/AppVG
        if [ -n "${OVIRT_CRYPT_SWAP2}" ]; then
            echo "SWAP2 /dev/AppVG/Swap2 /dev/mapper/ovirt-crypt-swap2 ${OVIRT_CRYPT_SWAP2}" >> /etc/ovirt-crypttab
        else
            mkswap -L "SWAP2" /dev/AppVG/Swap2
            echo "/dev/AppVG/Swap2 swap swap defaults 0 0" >> /etc/fstab
        fi
    fi

    local use_data=1
    if [ "$DATA2_SIZE" -eq -1 ]; then
        log "Creating data2 partition with remaining free space"
        lvcreate --name Data2 -l 100%FREE /dev/AppVG
        use_data=0
    elif [ "$DATA2_SIZE" -gt 0 ]; then
        log "Creating data2 partition"
        lvcreate --name Data2 --size ${DATA2_SIZE}M /dev/AppVG
        use_data=0
    fi

    if [ "$use_data" = 0 ]; then
        mke2fs -j -t ext4 /dev/AppVG/Data2 -L "DATA"
        tune2fs -c 0 -i 0 /dev/AppVG/Data2
        echo "/dev/AppVG/Data2 /data2 ext4 defaults,noatime 0 0" >> /etc/fstab
    fi

    if [ "$use_data" = 0 ]; then
        log "Mounting data2 partition"
        mount_data2
    fi
    log "Completed AppVG!"

}

perform_partitioning()
{
    if [ -z "$HOSTVGDRIVE" -a "$OVIRT_ISCSI_ENABLED" != "y" ]; then
        printf "\nNo storage device selected.\n"
        return
    fi

    if [ -z "$BOOTDRIVE" -a "$OVIRT_ISCSI_ENABLED" = "y" ]; then
        printf "\nNo storage device selected.\n"
        return
    fi
    start_log

    log "Saving parameters"
    unmount_config /etc/default/ovirt

    log "Removing old LVM partitions"
    wipe_volume_group HostVG
    wipe_volume_group AppVG
    wipe_lvm_on_disk "$HOSTVGDRIVE"
    [ -n "${APPVGDRIVE}" ] && wipe_lvm_on_disk "$APPVGDRIVE"
    wipe_lvm_on_disk "$ROOTDRIVE"

    # begin critical section
    set -e
    set -x

    MEM_SIZE_MB=$(echo "scale=0; $MEM_SIZE_MB / 1024;" | bc -l)
    boot_size_si=$(echo "scale=0; $BOOT_SIZE * (1024 * 1024) / (1000 * 1000)" | bc -l)

    if [ "$OVIRT_ISCSI_ENABLED" = "y" ]; then
        log "iSCSI enabled, partitioning boot drive: $BOOTDRIVE"
        wipe_partitions "$BOOTDRIVE"
        reread_partitions "$BOOTDRIVE"
        log "Creating boot partition"
        while true; do
            set +e
            parted -s "$BOOTDRIVE" "mklabel ${LABEL_TYPE} mkpart primary ext2 2048s ${boot_size_si}M"
            set -e
            reread_partitions "$BOOTDRIVE"
            if [ -e "${BOOTDRIVE}1" -o "${BOOTDRIVE}p1" ]; then
                break
            fi
        done
        partboot="${BOOTDRIVE}1"
        if [ ! -e "$partboot" ]; then
            partboot="${BOOTDRIVE}p1"
        fi
        # sleep to ensure filesystems are created before continuing
        sleep 10
        mke2fs "${partboot}" -L Boot
        tune2fs -c 0 -i 0 "${partboot}"
        if [ "$OVIRT_ISCSI_HOSTVG" = "y" ]; then
            # XXX Can iscsi hostvg span multiple drives?
            # for drv in $HOSTVGDRIVE
            log "Partitioning root drive: $HOSTVGDRIVE"
            wipe_partitions "$HOSTVGDRIVE"
            reread_partitions "$HOSTVGDRIVE"
            log "Labeling Drive: $HOSTVGDRIVE"
            set +e
            until parted -s "$HOSTVGDRIVE" "mklabel ${LABEL_TYPE}"; do
                log "retrying iscsi-hostvg:mklabel"
                sleep 1
            done
            set -e
            create_hostvg
        fi
        log "Completed!"
        return
    fi

    if [ "$OVIRT_ROOT_INSTALL" = "y" ]; then
        log "Partitioning root drive: $ROOTDRIVE"
        wipe_partitions "$ROOTDRIVE"
        reread_partitions "$ROOTDRIVE"
        log "Creating Root and RootBackup Partitions"
        let RootBackup_end=${ROOT_SIZE}*2+${EFI_SIZE}
        let Root_end=${ROOT_SIZE}+${EFI_SIZE}
        while true; do
            set +e
            parted -s "$ROOTDRIVE" "mklabel ${LABEL_TYPE} mkpart primary fat32 2048s ${EFI_SIZE}M mkpart primary ext2 ${EFI_SIZE} ${Root_end}M mkpart primary ext2 ${Root_end}M ${RootBackup_end}M"
            set -e
            reread_partitions "$ROOTDRIVE"
            if [ -e "${ROOTDRIVE}3" -o -e "${ROOTDRIVE}p3" ]; then
                break
            fi
        done
        partefi="${ROOTDRIVE}1"
        partroot="${ROOTDRIVE}2"
        partrootbackup="${ROOTDRIVE}3"
        if [ ! -e "$partroot" ]; then
            partefi="${ROOTDRIVE}p1"
            partroot="${ROOTDRIVE}p2"
            partrootbackup="${ROOTDRIVE}p3"
        fi
        ln -snf "${partefi}" /dev/disk/by-label/EFI
        mkfs.vfat "${partefi}" -n EFI
        ln -snf "${partroot}" /dev/disk/by-label/Root
        mke2fs -t ext2 "${partroot}" -L Root
        tune2fs -c 0 -i 0 "${partroot}"
        ln -snf "${partrootbackup}" /dev/disk/by-label/RootBackup
        mke2fs -t ext2 "${partrootbackup}" -L RootBackup
        tune2fs -c 0 -i 0 "${partrootbackup}"
    fi

    oldIFS="$IFS"
    IFS="$SEP"
    for drv in $HOSTVGDRIVE; do
        if [ "$ROOTDRIVE" != "$drv" ]; then
            wipe_partitions "$drv"
            reread_partitions "$drv"
            log "Labeling Drive: $drv"
            set +e
            until parted -s "$drv" "mklabel ${LABEL_TYPE}"; do
                log "retrying hostvg:mklabel"
                sleep 1
            done
            set -e
        fi
    done
    IFS="$oldIFS"

    create_hostvg
    [ -n "${APPVGDRIVE}" ] && create_appvg
    if [ -n "${OVIRT_CRYPT_SWAP2}" -o -n "${OVIRT_CRYPT_SWAP}" ]; then
        ovirt_store_config /etc/ovirt-crypttab
    fi
    stop_log
}

do_confirm()
{

    if [[ -z "$ROOTDRIVE" && "$OVIRT_ISCSI_ENABLED" != "y" ]]; then
        printf "\nNo Root storage device selected.\n"
        return
    fi

    if [[ -z "$HOSTVGDRIVE" ]]; then
        printf "\nNo HostVG storage device selected.\n"
        return
    fi

    while true; do
        sp='                                                    '
        w='!!WARNING'
        wb="$w"'!!'
        w8="$w$w$w$w$w$w$w$w"
        printf '%s!!\n' \
          "$w8" \
          "$w8" \
          "$wb$sp$w" \
          "$wb$sp$w" \
          "$wb    If you proceed, all data on your selected storage  $w" \
          "$wb    device will be destroyed and your hard disk        $w" \
          "$wb    will be irreversably reconfigured                  $w" \
          "$wb$sp$w" \
          "$wb$sp$w" \
        "$w8" \
        "$w8"

        if ask_yes_or_no "Do you wish to proceed ([Y]es/[N]o)?"; then
            if check_partition_sizes; then
                perform_partitioning
                exit 0
            fi
        else
            return
        fi
        # store networking config since it was created before storage was established for iscsi targets
        if [ "$OVIRT_ISCSI_NETWORKING" = "y" ]; then
            ovirt_store_config \
        /etc/sysconfig/network-scripts/ifcfg* \
        /etc/ntp.conf
        fi
    done
}

do_iscsi_target()
{
if ! network_up ; then
    printf "Networking must be configured prior to configuring an iscsi target.\n\n"
    # allow network config without setting up storage first
    augtool <<EOF
set /files/etc/default/ovirt/OVIRT_ISCSI_NETWORK_CONFIG y
EOF
    exit 99
fi

while true; do
    OPTIONS="\"Target IP\" \"Target Port\"" #\"CHAP Username\" \"CHAP Password\""
    printf "\nPress Enter to leave option blank or Q to quit (default Target Port is 3260)\n"
    eval set $OPTIONS
    PS3="Choose an option: "
    for OPTION in "$@"; do
        while true; do
            read -ep "Enter $OPTION: "
            if [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
                return
            fi

        if [ "$OPTION" = "Target IP" ]; then
            if is_valid_ipv4 $REPLY; then
                OVIRT_ISCSI_TARGET_IP="$REPLY"
                break;
            else
                printf "\nThe address $REPLY is not a valid IPv4 address.\n"
        fi

            elif [ "$OPTION" = "Target Port" ]; then
                OVIRT_ISCSI_TARGET_PORT="$REPLY"
                if [ -z "$REPLY" ]; then
                    OVIRT_ISCSI_TARGET_PORT="3260"
                    break;
                else
                    break;
                fi

            elif [ "$OPTION" = "CHAP Username" ]; then
                OVIRT_ISCSI_CHAP_USERNAME="$REPLY"
                break

            elif [ "$OPTION" = "CHAP Password" ]; then
                OVIRT_ISCSI_CHAP_PASSWORD="$REPLY"
                break;
            fi
        done
    done

    cat <<EOF

The iSCSI target be configured as follows:
================================================
    Target IP:   $OVIRT_ISCSI_TARGET_IP
  Target Port:   $OVIRT_ISCSI_TARGET_PORT

EOF
#     Username:   $OVIRT_ISCSI_CHAP_USERNAME
#     Password:   $OVIRT_ISCSI_CHAP_PASSWORD
#EOF

if ask_yes_or_no "Is this correct ([Y]es/[N]o)?" true true; then

    OVIRT_ISCSI_ENABLED="y"
    augtool <<EOF
set /files/etc/default/ovirt/OVIRT_ISCSI_ENABLED y
set /files/etc/default/ovirt/OVIRT_ISCSI_TARGET_IP $OVIRT_ISCSI_TARGET_IP
set /files/etc/default/ovirt/OVIRT_ISCSI_TARGET_PORT $OVIRT_ISCSI_TARGET_PORT
EOF

    if [[ -n "$OVIRT_ISCSI_CHAP_USERNAME" && -n "$OVIRT_ISCSI_CHAP_PASSWORD" ]]; then
        log "setting iscsid.conf username/password"
        augtool <<EOF
set /files/etc/iscsi/iscsid.conf/node.session.auth.authmethod CHAP
set /files/etc/iscsi/iscsid.conf/node.session.auth.username $OVIRT_ISCSI_CHAP_USERNAME
set /files/etc/iscsi/iscsid.conf/node.session.auth.password $OVIRT_ISCSI_CHAP_PASSWORD
set /files/etc/default/ovirt/OVIRT_ISCSI_CHAP_USERNAME $OVIRT_ISCSI_CHAP_USERNAME
set /files/etc/default/ovirt/OVIRT_ISCSI_CHAP_PASSWORD $OVIRT_ISCSI_CHAP_PASSWORD
EOF
    fi

    iscsiadm -p "$OVIRT_ISCSI_TARGET_IP:$OVIRT_ISCSI_TARGET_PORT" -m discovery -t sendtargets
    log "Restarting iscsi service"
    service iscsi restart

ISCSI_NODE_NAMES="$(iscsiadm -m discovery -p $OVIRT_ISCSI_TARGET_IP:$OVIRT_ISCSI_TARGET_PORT -t sendtargets|awk {'print $2'})"

printf "\n\n Select iSCSI target node\n\n" >&2
select OVIRT_ISCSI_NODE_NAME in $ISCSI_NODE_NAMES ; do
log " Selected Node Name: $OVIRT_ISCSI_NODE_NAME"
break;
done

augtool <<EOF
set /files/etc/default/ovirt/OVIRT_ISCSI_ENABLED y
set /files/etc/default/ovirt/OVIRT_ISCSI_TARGET_IP $OVIRT_ISCSI_TARGET_IP
set /files/etc/default/ovirt/OVIRT_ISCSI_TARGET_PORT $OVIRT_ISCSI_TARGET_PORT
set /files/etc/default/ovirt/OVIRT_ISCSI_NODE_NAME $OVIRT_ISCSI_NODE_NAME
EOF
break;
fi
done

if mount_iscsi_liveos; then
    if ! [ -d /liveos/lib/modules/$(uname -r) ]; then
        printf "Running kernel version does not match version installed to iscsi root file system, aborting\n\n"
        exit 99
    fi
fi
}

cross_check_host_app()
{
oldIFS="$IFS"
IFS="$SEP"
for hdrv in $HOSTVGDRIVE; do
    for adrv in $APPVGDRIVE; do
        if [ "${hdrv}" = "${adrv}" ]; then
            # Skip disk partitioning, AppVG overlaps with HostVG
            IFS="$oldIFS"
            return 1
        fi
    done
done
IFS="$oldIFS"
return 0
}

MEM_SIZE_MB=$(awk '/MemTotal:/ { print $2 }' /proc/meminfo)
case $MEM_SIZE_MB in
    ''|*[^0-9]*) die failed to get system memory size;;
esac
MEM_SIZE_MB=$(echo "scale=0; $MEM_SIZE_MB / 1024;" | bc -l)

overcommit=${OVIRT_OVERCOMMIT:-$default_overcommit}
# we multiply the overcommit coefficient by 10 then divide the
# product by 10 to avoid decimals in the result
OVERCOMMIT_SWAP_SIZE=$(echo "scale=0; (${MEM_SIZE_MB} * (${overcommit} * 10))/10;" | bc -l)

# add to the swap the amounts from http://kbase.redhat.com/faq/docs/DOC-15252
MEM_SIZE_GB=$(echo "scale=0; $MEM_SIZE_MB/1024;" | bc -l)
if [ $MEM_SIZE_GB -le 4 ]; then
    BASE_SWAP_SIZE=2048
elif [ $MEM_SIZE_GB -le 16 ]; then
    BASE_SWAP_SIZE=4096
elif [ $MEM_SIZE_GB -le 64 ]; then
    BASE_SWAP_SIZE=8192
else
    BASE_SWAP_SIZE=16384
fi

CALC_SWAP_SIZE=$(echo "scale=0; ${BASE_SWAP_SIZE} + ${OVERCOMMIT_SWAP_SIZE};" | bc -l)

BOOT_SIZE=$default_boot_size
SWAP_SIZE=${OVIRT_VOL_SWAP_SIZE:-$CALC_SWAP_SIZE}
ROOT_SIZE=$default_root_size
CONFIG_SIZE=${OVIRT_VOL_CONFIG_SIZE:-$default_config_size}
LOGGING_SIZE=${OVIRT_VOL_LOGGING_SIZE:-$default_logging_size}
DATA_SIZE=${OVIRT_VOL_DATA_SIZE:-$default_data_size}
SWAP2_SIZE=${OVIRT_VOL_SWAP2_SIZE:-$default_swap2_size}
DATA2_SIZE=${OVIRT_VOL_DATA2_SIZE:-$default_data2_size}
EFI_SIZE=${default_efi_size}

if [ -n "$OVIRT_INIT" ]; then
    # if present, use drive(s) selected with 'ovirt_init' boot parameter
    ROOTDRIVE=
    HOSTVGDRIVE=
    oldIFS="$IFS"
    IFS="$SEP"
    for drv in $OVIRT_INIT; do
        DRIVE="$(translate_multipath_device "$drv")"
        if [ -z "$ROOTDRIVE" ]; then
            # XXX assumes first is ROOTDRIVE
            ROOTDRIVE="$DRIVE"
        fi
        if [ -n "$HOSTVGDRIVE" ]; then
            HOSTVGDRIVE="$HOSTVGDRIVE${SEP}$DRIVE"
        else
            HOSTVGDRIVE="$DRIVE"
        fi
    done
    IFS="$oldIFS"

    OVIRT_ROOT_INSTALL="y"
    get_drive_size "$ROOTDRIVE" ROOTDRIVESPACE
fi

if [ -n "$OVIRT_INIT_APP" ]; then
    if [ ${SWAP2_SIZE} -ne 0 -o ${DATA2_SIZE} -ne 0 ]; then
        APPVGDRIVE=
        oldIFS="$IFS"
        IFS="$SEP"
        for drv in $OVIRT_INIT_APP; do
            DRIVE="$(translate_multipath_device "$drv")"
            if [ -n "$APPVGDRIVE" ]; then
                APPVGDRIVE="$APPVGDRIVE${SEP}$DRIVE"
            else
                APPVGDRIVE="$DRIVE"
            fi
        done
        IFS="$oldIFS"
        cross_check_host_app || {
            log "Skip disk partitioning, AppVG overlaps with HostVG"
            exit 1
        }
    fi
else
    { [ ${SWAP2_SIZE} -ne 0 ] || [ $DATA2_SIZE -ne 0 ]; } && {
        log "Missing device parameter for AppVG: unable to partition any disk"
        exit 2
    }
fi

# if the node is Fedora then use GPT, otherwise use MBR
if [ -f /etc/fedora-release ]; then
    LABEL_TYPE="gpt"
else
    LABEL_TYPE="msdos"
fi

if [ "$1" = "AUTO" ]; then
    log "Beginning automatic disk partitioning."
    if [ -n "$OVIRT_INIT" ]; then
        # Logic for automatic partitioning
        # If HostVG/AppVG exists on a disk other than $DRIVE, fail
        # If HostVG/AppVG exists on $DRIVE, then partition only if
        # firstboot is specified
        # Else, partition
        if check_existing_hostvg >/dev/null 2>&1 \
            || check_existing_hostvg "" "" AppVG ; then
            if check_existing_hostvg "$HOSTVGDRIVE"; then
                log "HostVG exists on a separate disk"
                log "Manual Intervention required"
                exit 1
            elif [ -n "$APPVGDRIVE" ] \
              && check_existing_hostvg "$APPVGDRIVE"; then
                log "AppVG exists on a separate disk"
                log "Manual Intervention required"
                exit 1
            else
                if is_firstboot; then
                    if check_partition_sizes; then
                        log "Partitioning hard disk..."
                        perform_partitioning
                        exit $?
                    else
                        log "storage_vol parameter can be used to reduce the size of partitions"
                        log "e.g. storage_vol=:SWAP_SIZE_IN_MB"
                        log "WARNING: you might have issues because you don't have enough swap"
                        log "to meet suggested minimum swap size."
                        exit 1
                    fi
                else
                    echo "Disk is already partitioned and firstboot not specified, Skipping partitioning"
                    exit 0
                fi
            fi
        else
            if check_partition_sizes; then
                log "Partitioning hard disk..."
                perform_partitioning
                exit $?
            else
                log "storage_vol parameter can be used to reduce the size of partitions"
                log "e.g. storage_vol=:SWAP_SIZE_IN_MB"
                log "WARNING: you might have issues because you don't have enough swap"
                log "to meet suggested minimum swap size."
            fi
        fi
    else
        log "Missing device parameter: unable to partition any disk"
        exit 2
    fi
else
    OPTIONS="\"Enable iSCSI Target\" \"Configure Storage\" \"Review\" \"Commit Changes And Quit\" \"Return To Menu\""
    eval set $OPTIONS
    PS3="Choose an option: "

    while true; do
        printf "\n\n Storage Configuration\n\n" >&2

        select OPTION in "$@"
        do
            case "$OPTION" in
                "Enable iSCSI Target") do_iscsi_target; break ;;
                "Configure Storage") do_configure ; break ;;
                "Review")    do_review    ; break ;;
                "Commit Changes And Quit") do_confirm   ; break ;;
                "Return To Menu")      printf "\nExiting.\n"; exit ;;
            esac
        done
    done
fi
