#!/bin/bash

ME=$(basename $0);

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


group_option=no
help_option=no


function check_help_option()
{
    for param; do
	if [ "$param" = "--help" ]; then
	    help_option=yes
	    return
	fi
	if echo $param | grep -q '^--'; then
	    continue
	fi
	if echo $param | grep -q '^-'; then
	    if echo $param | grep -q '[h?]'; then
		help_option=yes
		return
	    fi
	fi
    done

    help_option=no
    return
}


function check_group_option()
{
    for param; do
	if [ "$param" = "--group" ]; then
	    group_option=yes
	    return
	fi
	if echo $param | grep -q '^--'; then
	    continue
	fi
	if echo $param | grep -q '^-'; then
	    if echo $param | grep -q 'g'; then
		group_option=yes
		return
	    fi
	fi
    done

    group_option=no
    return
}


function curr_keys_as_params()
{
    key_keys=$(set | grep '^ec2_public_keys_' | cut -f1 -d=);
    for key in $key_keys; do
        a_val=$(eval "echo \$$key");
        echo "-k $(echo $a_val | cut -f1 -d=) "
    done
}


function curr_groups_as_params()
{
    if [ "$group_option" = "yes" ]; then
	return
    fi

    for grp in $ec2_security_groups; do
        grp=$(echo $grp | sed 's/+/ /g' | perl -MURI::Escape -lne 'print uri_unescape($_)');
        echo -n " -g '$grp' "
    done
}


function show_help()
{
    usage_banner;
    cat <<EOF

Usage:  $ME [-h] [EC2-RUN-INSTANCES-ARGS]

Start a new Gluster Storage Virtual Appliance instance.
The optional EC2-RUN-INSTANCES-ARGS are any arguments accepted
by \`ec2-run-instances' tool and override the defaults.

Miscellaneous:
  -h                        display this help and exit

Example:
  $ME
  $ME --type m1.xlarge
EOF
}


function wait_boot()
{
    num=$#;
    oldnum=0;
    retry=13;

    while [ $num -ne 0 ]; do
        echo -n "Waiting for $num instance(s) to boot ...";

        num=$(ec2-describe-instances --region $ec2_placement_region $@ | grep pending | wc -l);

        if [ $oldnum -eq $num ]; then
            # detect inactivity for 10 attempts
            retry=$(( $retry - 1 ));
            if [ $retry -eq 0 ]; then
                echo " Timeout";
                exit 1;
            fi
        else
            oldnum=$num;
            retry=10;
        fi

        if [ $num -eq 0 ]; then
            echo " done.";
        else
            sleep 3;
            echo;
        fi
    done
}


function wait_glusterd()
{
    num=0;
    oldnum=0;
    retry=42;
    total=$#;

    hosts=$(echo "$HOSTDUMP" | awk '{print $2}');

    while [ $num -ne $# ]; do
        left=$(($total - $num));
        echo -n "Waiting for $left instance(s) to start Gluster services ...";

        num=$(nmap -n -p 24007 $hosts 2>/dev/null | grep 24007 | grep open | wc -l);

        if [ $oldnum -eq $num ]; then
            # detect inactivity for 10 attempts
            retry=$(( $retry - 1 ));
            if [ $retry -eq 0 ]; then
                echo " Timeout";
                exit 1;
            fi
        else
            oldnum=$num;
            retry=10;
        fi

        if [ $num -eq $# ]; then
            echo " done.";
        else
            echo " (still booting)"
            sleep 13;
        fi
    done
}


function peer_probe()
{
    instances=$@;

    echo -n "Probing the new instances into the Gluster network ... "

    for instance in $instances; do
        host=$(echo "$HOSTDUMP" | grep $instance | awk '{print $2}');
        echo "gluster peer probe $host ($instance) ..."
        gluster peer probe $host;
        sleep 1;
    done
}


function print_hostnames()
{
    HOSTDUMP="$(ec2-describe-instances --region $ec2_placement_region $@ | grep INSTANCE | cut -f2,5)";
    echo;
    ( cat <<EOF
 Instance    Hostname
----------  ----------
$HOSTDUMP
EOF
) | column -t
    echo;

}


function display_next()
{
        cat << EOF
================================================================================
Details of the launched instances are displayed above.

You would also want to provision storage on those instances by logging in into
them and running the gluster-provision-storage command, like this:

  sh# ssh <HOSTNAME>
  ...
  remote-sh# gluster-provision-storage <SIZE_GiB>
  ...
  remote-sh# exit
  sh#

EOF
}


function main()
{
    check_help_option "$@"
    check_group_option "$@"
    if [ "$help_option" = "yes" ]; then
	show_help
	exit 1
    fi

    set -e

    assert_creds;

    strapout=/tmp/metastrap.out.$$;

    gluster-ami-metastrap $strapout;

    echo -n "Launching EC2 instance(s) ... "
    instances=$(eval "ec2-run-instances --region $ec2_placement_region \
        $@ \
        -t $ec2_instance_type \
        -f $strapout \
        -z $ec2_placement_availability_zone \
        $(curr_keys_as_params) \
        $(curr_groups_as_params) \
        $ec2_ami_id" | grep INSTANCE | cut -f2);

    rm -f /tmp/metastrap.out.$$;

    if [ -z "$instances" ]; then
        echo "0 instances (failed)";
        exit 1;
    fi

    echo "("$instances")";

    gluster-ami-tagmyself $instances | grep -vi Calculating;

    wait_boot $instances;

    print_hostnames $instances;

    wait_glusterd $instances;

    peer_probe $instances;

    display_next;
}

main "$@";
