#!/usr/bin/env python
#

"""
ec2launch: Launch Amazon AWS EC2 instance
"""

import json
import os
import random
import sys
import time
from optparse import OptionParser

import boto
import ec2common

import gtermapi

ssh_dir = os.path.expanduser("~/.ssh")
gterm_user = "ubuntu"

usage = "usage: %prog [-h ... ] <instance-tagname>"

form_parser = gtermapi.FormParser(usage=usage, title="Create Amazon EC2 instance with the following tag: ", command="ec2launch -f")
form_parser.add_argument(label="", help="Instance name")
form_parser.add_option("type", ("", "t1.micro", "m1.small", "m1.medium", "m1.large"), help="Instance type")
form_parser.add_option("key_name", "ec2key", help="Instance management SSH key name")
form_parser.add_option("ami", "ami-82fa58eb", help="Instance OS (default: Ubuntu 12.04LTS)")
form_parser.add_option("security", "default", help="Security group")
form_parser.add_option("domain", help="Instance domain")
form_parser.add_option("connect_to_gterm", "", help="Connect to GraphTerm")
form_parser.add_option("start_gterm", False, help="Start GraphTerm")
form_parser.add_option("pylab", False, help="Install PyLab")
form_parser.add_option("oshell", False, help="OTrace shell")
form_parser.add_option("dry_run", False, help="Dry run")

form_parser.add_option("fullpage", False, short="f", help="Fullpage display", raw=True)
form_parser.add_option("text", False, short="t", help="Text only", raw=True)

(options, args) = form_parser.parse_args()

if args:
    instance_tag = args[0]
elif options.domain:
    instance_tag = options.domain
elif not options.dry_run:
    if not gtermapi.Lterm_cookie or options.text:
        print >> sys.stderr, form_parser.get_usage()
        sys.exit(1)
    gtermapi.write_form(form_parser.create_form(), command="ec2launch -f")
    sys.exit(1)
    
if options.domain:
    subdomain_name, sep, top_level_domain = options.domain.partition(".")
else:
    subdomain_name, top_level_domain = "", ""

key_file = os.path.join(ssh_dir, options.key_name+".pem")

if not os.path.exists(ssh_dir):
    print >> sys.stderr, "ec2launch: %s directory not found!" % ssh_dir
    sys.exit(1)

startup_script = """#!/bin/bash
set -e -x
apt-get update && apt-get upgrade -y
apt-get install -y python-setuptools
easy_install tornado
easy_install graphterm
sudo gterm_setup
"""

if options.pylab:
    startup_script += "apt-get install -y python-numpy python-scipy python-matplotlib\n"

command_format = "sudo -u "+gterm_user+" -i %s --daemon=start"
if options.oshell:
    command_format += " --oshell"

if options.start_gterm:
    if not options.domain:
        raise Exception("Must specify domain to start GraphTerm server")
    startup_script += (command_format % "gtermserver") + " --auth_code=none --host="+options.domain+"\n"

if options.connect_to_gterm:
    if not options.domain:
        raise Exception("Must specify domain to connect to GraphTerm server")
    startup_script += (command_format % "gtermhost") + " --server_addr="+options.connect_to_gterm+" "+subdomain_name+"\n"

# Connect to EC2
ec2 = boto.connect_ec2()

# Create key pair, if needed
if not os.path.exists(key_file):
    key_pair = ec2.create_key_pair(options.key_name)
    key_pair.save(ssh_dir)
    os.chmod(key_file, 0600)

if options.dry_run:
    print >> sys.stderr, "run_instances:", dict(image_id=options.ami,
                                                instance_type=options.type,
                                                key_name=options.key_name,
                                                security_groups=[options.security],
                                                user_data=startup_script)
    sys.exit(1)

# Launch instance
reservation = ec2.run_instances(image_id=options.ami,
                                instance_type=options.type,
                                key_name=options.key_name,
                                security_groups=[options.security],
                                user_data=startup_script)
instance = reservation.instances[0]

# Wait for instance to start running
Status_template =  """<em>Creating instance</em> <b>%s</b>: status=<b>%s</b> (waiting %ds)"""

status = instance.update()
start_time = time.time()
while status == "pending":
    timesec = int(time.time() - start_time)
    gtermapi.write_html(Status_template % (instance_tag, status, timesec), display="fullpage")
    time.sleep(3)
    status = instance.update()

if status != "running":
    print >> sys.stderr, "ec2launch: ERROR Failed to launch instance: %s" % status
    sys.exit(1)

# Tag instance
if instance_tag:
    instance.add_tag(instance_tag)

instance_id = reservation.id
instance_obj = None
all_instances = ec2.get_all_instances()
for r in all_instances:
    if r.id == instance_id:
        instance_obj = r.instances[0]
        break

if not instance_obj:
    print >> sys.stderr, "ec2launch: ERROR Unable to find launched instance: %s" % status
    sys.exit(1)

instance_domain = instance_obj.public_dns_name

if options.domain:
    route53conn, zone = ec2common.get_zone(top_level_domain)
    if not zone:
        print >> sys.stderr, "No Route53 zone found for %s" % options.domain

    # Create new CNAME entry pointing to instance public DNS
    ec2common.cname(route53conn, zone, options.domain, instance_domain)

print "Created EC2 instance: id=%s, domain=%s" % (instance_id, instance_domain)
