#!/usr/bin/env python

# Creates an Amazon EC2 virtual machine (an instance) and runs some
# shell commands on it before terminating it. Just an example.
# Stephane Bortzmeyer <stephane+amazon@bortzmeyer.org>

# We use Boto, the Python interface to Amazon EC2
# Official site http://code.google.com/p/boto/
# Documentation on Boto and EC2 http://readthedocs.org/docs/boto/en/latest/ec2_tut.html
# Complete example http://www.takaitra.com/posts/384
# A good starting point http://aws.amazon.com/articles/3998

# For SSH, all SSH libraries for Python are junk (as of 2011-10-13).
# Too low-level (libssh2), too buggy (paramiko), too complicated
# (both), too poor in features (no use of the agent, for instance). We
# use the subprocess module and the OpenSSH CLI executable.

import boto, boto.ec2
import os, sys, time, subprocess

# You may change these
COMMANDS="(id; uname -a; free; dig @d.nic.fr CH TXT hostname.bind)"
MAX_TESTS=5
KEYDIR='.'
KEY='test-b'
USERNAME='root'
REGION='eu-west-1'
AMI='ami-02103876'

my_region = boto.ec2.get_region(REGION)

if not os.environ.has_key('AWS_ACCESS_KEY_ID') and \
       not os.environ.has_key('AWS_SECRET_ACCESS_KEY'):
    print >>sys.stderr, \
          "You need to define the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY"
    sys.exit(1)

conn = my_region.connect()

reservation = conn.run_instances(AMI, key_name=KEY)
instance = reservation.instances[0]
# TODO: limit the number of tests
while not instance.update() == 'running':
    time.sleep(2) # Let the instance start up
print "Instance %s started, as %s" % (instance.id, instance.dns_name)

tests = 0
over = False
while not over:
    ssh = subprocess.Popen(
        ["ssh", "-o", "StrictHostKeyChecking no", \
         "-i" , "%s/%s.pem" % (KEYDIR, KEY), "%s@%s" % (USERNAME, instance.dns_name), \
         COMMANDS],
        shell=False,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    result = ssh.stdout.readlines()
    if result == []:
        if tests >= MAX_TESTS:
            error = ssh.stderr.readlines()
            print >>sys.stderr, "ERROR: %s" % error
            print >>sys.stderr, "Too many ssh attempts to %s, giving in" % \
                  instance.dns_name
            over = True
        else:
            tests += 1
            time.sleep(2)
    else:
        print result
        error = ssh.stderr.readlines()
        if error != []:
            print >>sys.stderr, "ERROR: %s" % error
        over = True
instance.stop()

