From f986ba2d03cacc6000ad264e2d71fd5591f89823 Mon Sep 17 00:00:00 2001 From: Alex Polvi Date: Sat, 17 Aug 2013 00:47:35 -0700 Subject: [PATCH 1/2] test(ami-test): basic script for testing ami and bootstrapping --- oem/ami/test_ami.sh | 117 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100755 oem/ami/test_ami.sh diff --git a/oem/ami/test_ami.sh b/oem/ami/test_ami.sh new file mode 100755 index 0000000000..5d45f41d10 --- /dev/null +++ b/oem/ami/test_ami.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# +# This expects to run on an EC2 instance. +# +# mad props to Eric Hammond for the initial script +# https://github.com/alestic/alestic-hardy-ebs/blob/master/bin/alestic-hardy-ebs-build-ami + +# This script will launch three ec2 nodes with shared user-data, and then +# then test of the cluster is bootstrapped + +# Set pipefail along with -e in hopes that we catch more errors +set -e -o pipefail + +USAGE="Usage: $0 -a ami-id + -a ami-id ID of the AMI to be tests (required) + -K KEY Path to Amazon API private key. + -C CERT Path to Amazon API key certificate. + -h this ;-) + -v Verbose, see all the things! + +This script must be run from an ec2 host with the ec2 tools installed. +" + +while getopts "a:K:C:hv" OPTION +do + case $OPTION in + a) AMI="$OPTARG";; + K) export EC2_PRIVATE_KEY="$OPTARG";; + C) export EC2_CERT="$OPTARG";; + h) echo "$USAGE"; exit;; + v) set -x;; + *) exit 1;; + esac +done + +if [[ $(id -u) -eq 0 ]]; then + echo "$0: This command should not be ran run as root!" >&2 + exit 1 +fi + +if [ -z "$AMI" ]; then + echo "AMI required" >&2 + echo "$USAGE" >&2 + exit 1 +fi + +# check to make sure this is a valid image +if ! ec2-describe-images -F image-id="$AMI" | grep -q "$AMI"; then + echo "Unknown image: $AMI" >&2 + exit 1 +fi + +key_name="autotest-`date +%s`" +key_file="/tmp/$key_name" +ec2-create-keypair $key_name | grep -v KEYPAIR > $key_file +chmod 600 $key_file + +sg_name=$key_name +sg=$(ec2-create-group $sg_name --description "$sg_name" | cut -f2) +ec2-authorize "$sg_name" -P tcp -p 4001 > /dev/null +ec2-authorize "$sg_name" -P tcp -p 7001 > /dev/null +ec2-authorize "$sg_name" -P tcp -p 22 > /dev/null + +# might be needed later for multi-zone tests +zoneurl=http://instance-data/latest/meta-data/placement/availability-zone +zone=$(curl --fail -s $zoneurl) +region=$(echo $zone | sed 's/.$//') + +token=$(dd if=/dev/urandom bs=8 count=1 2> /dev/null| sha1sum|cut -d' ' -f1) + +instances=$(ec2-run-instances \ + --user-data "$token" \ + --instance-type "t1.micro" \ + --instance-count 3 \ + --group "$sg_name" \ + --key "$key_name" $AMI | \ + grep INSTANCE | cut -f2) + +# little hack to create a describe instances command that only +# pulls data for these instances +ec2_cmd=$(echo $instances | sed 's/ / --filter instance-id=/g') +ec2_cmd="ec2-describe-instances --filter instance-id=$ec2_cmd" + +while $ec2_cmd | grep INSTANCE | grep -q pending + do sleep 10; done + +declare -a ips=($($ec2_cmd | grep INSTANCE | cut -f4)) + +# sleep until all the sockets we need come up +for host in ${ips[@]}; do + timeout 30 perl -MIO::Socket::INET -e " + until(new IO::Socket::INET('$host:22')){sleep 1}" + timeout 30 perl -MIO::Socket::INET -e " + until(new IO::Socket::INET('$host:4001')){sleep 1}" + timeout 30 perl -MIO::Socket::INET -e " + until(new IO::Socket::INET('$host:7001')){sleep 1}" +done + +test_key="v1/keys/test" +# XXX: the sleeps *should never* be required, this is a bug in etcd +sleep 1 +curl --fail -s -L "${ips[0]}:4001/$test_key" -d value="$token" > /dev/null +sleep 1 +for host in ${ips[@]}; do + if ! curl --fail -s -L "${host}:4001/$test_key" | grep -q $token; then + echo "etcd bootstrap appears to have failed for $host" >&2 + exit 1 + fi +done + +ec2-terminate-instances $instances > /dev/null +while ! $ec2_cmd | grep INSTANCE | grep -q terminated + do sleep 10; done + +ec2-delete-group $sg_name > /dev/null +ec2-delete-keypair $key_name > /dev/null +rm $key_file From a191ff99731acabe10c838cad733df0ac72f5500 Mon Sep 17 00:00:00 2001 From: Alex Polvi Date: Sun, 18 Aug 2013 09:15:15 -0700 Subject: [PATCH 2/2] Used uuidgen Refacted timeout section to be a loop Added output for progress Fixed indentation --- oem/ami/test_ami.sh | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/oem/ami/test_ami.sh b/oem/ami/test_ami.sh index 5d45f41d10..798827cee6 100755 --- a/oem/ami/test_ami.sh +++ b/oem/ami/test_ami.sh @@ -50,6 +50,7 @@ if ! ec2-describe-images -F image-id="$AMI" | grep -q "$AMI"; then exit 1 fi +echo -n "Creating keys and security group... " key_name="autotest-`date +%s`" key_file="/tmp/$key_name" ec2-create-keypair $key_name | grep -v KEYPAIR > $key_file @@ -60,14 +61,16 @@ sg=$(ec2-create-group $sg_name --description "$sg_name" | cut -f2) ec2-authorize "$sg_name" -P tcp -p 4001 > /dev/null ec2-authorize "$sg_name" -P tcp -p 7001 > /dev/null ec2-authorize "$sg_name" -P tcp -p 22 > /dev/null +echo "OK ($key_name)" # might be needed later for multi-zone tests zoneurl=http://instance-data/latest/meta-data/placement/availability-zone zone=$(curl --fail -s $zoneurl) region=$(echo $zone | sed 's/.$//') -token=$(dd if=/dev/urandom bs=8 count=1 2> /dev/null| sha1sum|cut -d' ' -f1) +token=$(uuidgen) +echo -n "Booting instances... " instances=$(ec2-run-instances \ --user-data "$token" \ --instance-type "t1.micro" \ @@ -75,7 +78,6 @@ instances=$(ec2-run-instances \ --group "$sg_name" \ --key "$key_name" $AMI | \ grep INSTANCE | cut -f2) - # little hack to create a describe instances command that only # pulls data for these instances ec2_cmd=$(echo $instances | sed 's/ / --filter instance-id=/g') @@ -88,26 +90,28 @@ declare -a ips=($($ec2_cmd | grep INSTANCE | cut -f4)) # sleep until all the sockets we need come up for host in ${ips[@]}; do - timeout 30 perl -MIO::Socket::INET -e " - until(new IO::Socket::INET('$host:22')){sleep 1}" - timeout 30 perl -MIO::Socket::INET -e " - until(new IO::Socket::INET('$host:4001')){sleep 1}" - timeout 30 perl -MIO::Socket::INET -e " - until(new IO::Socket::INET('$host:7001')){sleep 1}" + for port in 22 4001 7001; do + timeout 30 perl -MIO::Socket::INET -e " + until(new IO::Socket::INET('$host:$port')){sleep 1}" + done done +echo "OK ($instances)" +echo -n "Testing etcd... " test_key="v1/keys/test" -# XXX: the sleeps *should never* be required, this is a bug in etcd +# XXX: the sleep *should never* be required, this is a bug in etcd sleep 1 curl --fail -s -L "${ips[0]}:4001/$test_key" -d value="$token" > /dev/null sleep 1 for host in ${ips[@]}; do if ! curl --fail -s -L "${host}:4001/$test_key" | grep -q $token; then echo "etcd bootstrap appears to have failed for $host" >&2 - exit 1 + exit 1 fi done +echo "OK" +echo -n "Cleaning up environment... " ec2-terminate-instances $instances > /dev/null while ! $ec2_cmd | grep INSTANCE | grep -q terminated do sleep 10; done @@ -115,3 +119,4 @@ while ! $ec2_cmd | grep INSTANCE | grep -q terminated ec2-delete-group $sg_name > /dev/null ec2-delete-keypair $key_name > /dev/null rm $key_file +echo "OK"