#!/bin/bash

#set -x

source //etc/common-utils.rc
source //etc/ec2.rc


function pick_next_free_array()
{
    arrays=$(awk '$1 ~ "^md[0-9]+" { split($1,a,"md"); print a[2] }' /proc/mdstat)
    #arrays=$(mdadm --examine --scan | cut -f2 -d' ' | sed -e 's/\/dev\/md//g' -e 's/\///g');
    for i in $(seq 0 1023); do
        if ! exists_in_list $i $arrays; then
            array=/dev/md$i;
            break;
        fi
    done
}


function create_array()
{
    pick_next_free_array;
    mdadm --create $array --level=0 --raid-devices=$stripe_pieces $array_devices;
    mdadm --examine --scan > /etc/mdadm.conf;
}


function create_attach_volume()
{
    volid=$(ec2-create-volume --region $ec2_placement_region -z $ec2_placement_availability_zone -s $piece_size | cut -f2);
    attvol=$(ec2-attach-volume --region $ec2_placement_region $volid -i $ec2_instance_id -d ${arrdev});
    myname=$(ec2-describe-tags --region $ec2_placement_region -F key=Name -F resource-id=$ec2_instance_id | cut -f5 | head -n1);
    mynum=${myname##*-};
    ec2-create-tags --region $ec2_placement_region $volid \
        --tag Domain=$DOMAIN \
        --tag Device=${arrdev} \
        --tag Instance=$ec2_instance_id \
        --tag Name="vol-$DOMAIN-$mynum" >/dev/null 2>&1;
}


function ebs_to_devs()
{
    cat <<EOF

You requested a volume of size ${SIZE_GiB}GiB. This will be created as a
software RAID over $stripe_pieces EBS volumes of ${piece_size}GiB each.

Creating $array_devices ...

EOF

    rm -f $array_devices

    for arrdev in $array_devices; do
	create_attach_volume &
    done

    wait_attach $array_devices
}


function format_mount()
{
    if [ -n "$1" ]; then
	//bin/gluster-provision-block -t $1 $array;
    else
	//bin/gluster-provision-block $array;
    fi
}


function validate_size()
{
    piece_size=$(( $SIZE_GiB / $stripe_pieces ));
}


function show_help()
{
    usage_banner;
    cat <<EOF

Usage:  $ME [-h] [-t FSTYPE] SIZE_GiB

Provision storage for this server.  This script creates a RAID0 array
composed of 8 EBS devices whose total disk space equals to SIZE_GiB.
SIZE_GiB is amount of storage in gibibytes (2^30) to provision.
The minimum value for SIZE_GiB is $min_size and the maximum value is $max_size.
SIZE_GiB should be a multiple of $stripe_pieces.

General:
  -t FSTYPE                 Prepare storage using FSTYPE filesystem.
                            Supported filesystems are ext3/ext4/xfs
                            (Default is ext4)

Miscellaneous:
  -h                        display this help and exit

Example:
  $ME 128
  $ME -t xfs 128
EOF
}


function main()
{
    # Parse command line arguments.
    while getopts :ht: OPT; do
	case "$OPT" in
	    h)
		show_help
		exit 0
		;;
	    t)
		fstype=$OPTARG
		case $fstype in
		    ext3 | ext4 | xfs)
			;;
		    *)
			echo "unknown fstype $fstype"
			show_help
			exit 1
			;;
		esac
		;;
	    \?)
                # getopts issues an error message
		echo "Invalid option: -$OPTARG"
		show_help
		exit 1
		;;
	    :)
		echo "Option -$OPTARG requires an argument."
		show_help
		exit 1
		;;
	esac
    done

    # Remove the switches we parsed above.
    shift `expr $OPTIND - 1`

    # We want only one non-option argument.
    if [ $# -ne 1 ]; then
	show_help
	exit 1
    fi

    new_size=$1
    if [ "$1" -eq "$1" 2>/dev/null ]; then
	if [ "$1" -lt $min_size -o "$1" -gt $max_size ]; then
	    echo "Invalid size: $1.  SIZE_GiB should be in between $min_size and $max_size (Recommended minimum size: 128 GiB)"
	    show_help
	    exit 1
	elif [ $(($1 % $stripe_pieces)) -ne 0 ]; then
	    new_size=$(( ($1 / $stripe_pieces) * $stripe_pieces ))
	    if [ $(($1 % $stripe_pieces)) -ge $(($stripe_pieces / 2)) ]; then
		(( new_size += stripe_pieces ))
	    fi
	    echo "Invalid size: $1.  Size should be a multiple of $stripe_pieces"
	    read -p "Do you want to use $new_size as the size instead? (y/n): " choice
            if [ $choice != "Y" -a $choice != "y" ]; then
                show_help
                exit 1
            fi
	fi
    else
	echo "Invalid number format: $1.  SIZE_GiB should be an integer between $min_size and $max_size (Recommended minimum size: 128 GiB)"
	show_help
	exit 1
    fi

    SIZE_GiB=$new_size;

    set -e

    validate_size $SIZE_GiB;

    assert_creds;

    pick_next_free_devices;

    ebs_to_devs;

    create_array;

    format_mount "$fstype";

    # tag the attached EBS volumes with export info
    device_list=$(mdadm --detail $array  | grep /dev/sd | awk '{ print $7 }');

    mountpt="/export/$(basename $array)";
    export_point="${ec2_hostname}:${mountpt}"

    volumes_in_this_instance=$(ec2-describe-tags --region $ec2_placement_region | grep $ec2_instance_id | grep volume | cut -f3)

    uuid=$(uuidgen);
    for device in $device_list; do
        volume=$(ec2-describe-volumes --region $ec2_placement_region $volumes_in_this_instance | grep ATTACHMENT | grep $device | cut -f2);

        echo "Tagging $volume with brick info $export_point ..."
        ec2-create-tags --region $ec2_placement_region $volume \
            --tag Brick=$export_point \
            --tag Array=$uuid >/dev/null 2>&1;
    done
}


main "$@";
