Source

ec2control / ec2control / ec2.py

Full commit
from boto.ec2.connection import EC2Connection
import time
import logging
import urllib2
import base64
log = logging.getLogger(__name__)

class CommandError(Exception):
    pass

class Instance(object):
    instance = None

    def __init__(self, config, name):
        self.config_file = config
        if name is None:
            if config.get("default_instance"):
                name = config["default_instance"]
            else:
                raise CommandError("No instance name specified")
        else:
            self.name = name

        if not config.has_section("instance_%s" % name):
            raise CommandError("Unknown instance name: %s" % name)
        self.config = config.section_dict("instance_%s" % name)
        self.descriptive_name = self.config['descriptive_name']
        self._conn = EC2Connection(config['aws_key'], config['aws_secret'])

    @property
    def ip_address(self):
        """Return the dynamic IP address of the instance"""
        if self.instance:
            return self.instance.ip_address
        else:
            return None

    @property
    def public_hostname(self):
        """Return the best internet name for the instance.

        If public_hostname is set, returns that.
        Else if public_ip_address is present, returns that.
        Otherwise returns ip_address.
        If the instance is not running, returns None
        in all cases.
        """

        if self.instance:
            if "public_hostname" in self.config:
                return self.config['public_hostname']
            elif "public_ip_address" in self.config:
                return self.config['public_ip_address']
            else:
                return self.instance.ip_address
        else:
            return None

    def start(self):
        instance_id = self.config['instance_id']
        log.info("Starting instance id: %s", instance_id)
        instances = self._conn.start_instances(instance_ids=[instance_id])

        self.instance = inst = instances[0]

        inst.update()
        while inst.state == 'pending':
            time.sleep(10)
            inst.update()

        # grease the wheels, seems to 
        # say "stopped" for a second here
        for i in xrange(10):
            if inst.state == 'stopped':
                time.sleep(10)
            else:
                break

        self.status = inst.state
        log.info("Status: %s", self.status)

        if self.status == "running":
            public_ip_address = self.config.get('public_ip_address', None)
            if public_ip_address is not None:
                if self._conn.associate_address(instance_id, public_ip_address):
                    log.info("Associated public ip address %s with instance", public_ip_address)
                    self.public_ip_address = public_ip_address

            dyndns_url = self.config_file.get('dyndns_url', None)
            public_hostname = self.config.get('public_hostname', None)
            if dyndns_url and public_hostname:
                username = self.config_file.get('dyndns_username')
                password = self.config_file.get('dyndns_password')
                url = dyndns_url % {'public_hostname':public_hostname, 'ip_address':self.instance.ip_address}
                log.info("Establishing dynamic dns: %s, userame %s, pw %s", url, username, password)               
                req = urllib2.Request(url)
                base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
                req.add_header("Authorization", "Basic %s" % base64string)
                result = urllib2.urlopen(req)
                result.read()