#!/bin/bash

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


function search_array()
{
    echo -n "Searching for dangling RAID array... "
    darrays=$(ec2-describe-volumes --show-empty-fields --region $ec2_placement_region -F availability-zone=$ec2_placement_availability_zone -F status=available -F tag:Domain=$DOMAIN | grep '^TAG.*Array' | awk '{ print $NF }' | sort -u)
    darray_count=$(echo $darrays | wc -w)
    echo "$darray_count found"
    if [ $darray_count -eq 0 ]; then
	echo "Nothing to do"
	exit 0
    fi
}


function select_array()
{
    if [ $darray_count -eq 1 ]; then
	brick=$(ec2-describe-volumes --show-empty-fields --region $ec2_placement_region -F availability-zone=$ec2_placement_availability_zone -F status=available -F tag:Domain=$DOMAIN -F tag:Array=$darrays | grep '^TAG.*Brick' | awk '{ print $NF }' | sort -u)
	read -p "Do you want to attach $brick ($darrays) [y/N]: " choice
	if [ "$choice" = "y" -o "$choice" = "Y" ]; then
	    darray=$darrays
	    return
	else
	    echo "Nothing to do"
	    exit 0
	fi
    fi

    echo "Dangling RAID arrays"
    echo "--------------------"
    i=1
    for darray in $darrays; do
	brick=$(ec2-describe-volumes --show-empty-fields --region $ec2_placement_region -F availability-zone=$ec2_placement_availability_zone -F status=available -F tag:Domain=$DOMAIN -F tag:Array=$darray | grep '^TAG.*Brick' | awk '{ print $NF }' | sort -u)
	printf "%6s) %s (%s)\n" $i $brick $darray
	(( i++ ))
    done
    printf "%6s) %s\n" 0 Exit
    echo
    (( count = i - 1 ))
    while true; do
	read -p "Select RAID array to attach (0 to $count): " choice
	if [ "$choice" -ge 0 -a "$choice" -le "$count" 2>/dev/null ]; then
	    break
	fi
	echo "error: Invalid selection $choice"
    done

    if [ "$choice" -eq 0 ]; then
	echo "Nothing to do"
	exit 0
    fi

    darray=$(echo $darrays | cut -d' ' -f${choice})
}


function search_ebs_of_array()
{
    echo "Searching EBS volumes associated to RAID array $darray..."
    ebss=$(ec2-describe-volumes --hide-tags --show-empty-fields --region $ec2_placement_region -F availability-zone=$ec2_placement_availability_zone -F status=available -F tag:Domain=$DOMAIN -F tag:Array=$darray | awk '{ print $2 }' | xargs)
    echo "Found: $ebss"

    ebs_count=$(echo $ebss | wc -w)

    if [ $ebs_count -ne $stripe_pieces ]; then
	echo "error: $stripe_pieces EBS volumes required, but $ebs_count found"
	exit 1
    fi
}


function attach_ebs_volumes()
{
    pick_next_free_devices
    cat /etc/mdadm.conf > /tmp/.mdadm.conf.orig.$$
    device_list=($array_devices)
    i=0
    echo "Attaching them now"
    for ebs in $ebss; do
	ec2-attach-volume --region $ec2_placement_region $ebs -i $ec2_instance_id -d ${device_list[$i]} >/dev/null 2>&1 &
	(( i++ ))
    done

    if ! wait_attach $array_devices; then
	exit 1
    fi

    mdadm --examine --scan > /etc/mdadm.conf
    mdadm --assemble --scan --auto=md

    devfile=${device_list[0]}
    if [ -L ${device_list[0]} ]; then
	devfile=$(readlink -f ${device_list[0]})
    fi
    blk=$(grep "^md[0-9]\+.*$(basename $devfile)\[" /proc/mdstat | awk '{ print $1 }')
    if [ -z "$blk" ]; then
	mdadm --examine --scan | while read line; do
	    uuid=$(echo $line | sed 's/.*UUID=\([^ ]*\).*/\1/g');
	    if ! grep -q $uuid /tmp/.mdadm.conf.orig.$$; then
		pick_next_free_array
		echo $line | sed "s#/dev/md[0-9]*#$array#" >> /tmp/.mdadm.conf.orig.$$
	    fi
	done
	mv -f /tmp/.mdadm.conf.orig.$$ /etc/mdadm.conf
	mdadm --assemble --scan --auto=md
	blk=$(grep "^md[0-9]\+.*$(basename $devfile)\[" /proc/mdstat | awk '{ print $1 }')
	if [ -z "$blk" ]; then
	    fail "unable to find newly attached array"
	fi
    fi
    rm -f /tmp/.mdadm.conf.*.$$
    devblk="/dev/$blk"
    mnt="/export/$blk";

    [ -e $mnt ] || mkdir -p $mnt
    [ -d $mnt ] || fail "$mnt is not a directory";
    grep -q " $mnt " /proc/mounts && fail "$mnt already has a mount";
    grep -q " $mnt/" /proc/mounts && fail "$mnt has a submount";
    awk '$1 !~ /^#/ { print $0 }' /etc/fstab | grep -q " $mnt " && fail "$mnt already has an entry in fstab";
    awk '$1 !~ /^#/ { print $0 }' /etc/fstab | grep -wq "$devblk" && fail "$devblk already has an entry in fstab";

    uuid=$(blkid -c /dev/null -o value $devblk | head -1); #sed -n 's/ID_FS_UUID=//p');
    fstype=$(blkid -c /dev/null -o value $devblk | tail -1);

    awk '$1 !~ /^#/ { print $0 }' /etc/fstab | grep -wq "$uuid" && fail "$uuid already has an entry in fstab";

    case $fstype in
	ext3 | ext4)
	    echo "UUID=$uuid $mnt $fstype defaults,user_xattr,acl 0 2" >> /etc/fstab || fail "Failed to update fstab";
	    ;;
	*)
	    echo "UUID=$uuid $mnt $fstype defaults 0 2" >> /etc/fstab || fail "Failed to update fstab";
	    ;;
    esac

    mount -v $mnt || fail "mounting $devblk on $mnt failed";

    old_brick_prefix=$(ec2-describe-volumes --show-empty-fields --region $ec2_placement_region -F availability-zone=$ec2_placement_availability_zone $ebs | grep '^TAG.*Brick' | awk '{ print $NF }')

    new_brick_prefix="${ec2_hostname}:$mnt"

    i=0
    for ebs in $ebss; do
	echo "Updating tags of $ebs"
	ec2-create-tags --region $ec2_placement_region $ebs \
	    --tag Device=${device_list[$i]} \
	    --tag Instance=$ec2_instance_id \
            --tag Brick=$new_brick_prefix >/dev/null 2>&1
	(( i++ ))
    done

    # TODO: show help message based on 'gluster volume info'
    cat <<EOF

================================================================================

$ME completed successfully.

$new_brick_prefix is available now.

Gluster volume configuration has to be updated with
$new_brick_prefix if any.
Check 'gluster volume info' output and update volumes by running gluster
replace-brick command.

  sh# gluster volume replace-brick <VOLNAME> \\
         $old_brick_prefix/<SUBDIR> \\
         $new_brick_prefix/<SUBDIR>

================================================================================

EOF
}


function show_help()
{
    usage_banner;
    cat <<EOF

Usage:  $ME [-h] [-o]

Attach dangling EBS volumes and create new export.

General:
  -o                        Select dangling RAID array automatically

Miscellaneous:
  -h                        display this help and exit

Example:
  $ME
EOF
}


function main()
{
    # Parse command line arguments.
    while getopts :ho OPT; do
	case "$OPT" in
	    h)
		show_help
		exit 0
		;;
	    o)
		auto=yes
		;;
	    \?)
                # 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 0 ]; then
	show_help
	exit 1
    fi

    search_array
    if [ "$auto" = "yes" ]; then
	darray_list=($darrays)
	darray=${darray_list[0]}
    else
	select_array
    fi
    search_ebs_of_array
    attach_ebs_volumes
}


main "$@";
