posted 16 Apr 2011

So i finally got around to signing up for an Free Tier Amazon EC2 account after reading alot about libcloud.
Combining libcloud with fabric gives huge opportunities when it comes to automating installations and deployment,
and with only a small amount of code.

First i had to install libcloud, which is installed through pip.

sudo apt-get install python-pip
sudo pip install libcloud
As fabric is available as an ubuntu package i used that, maybe there is a newer version available in pip but i haven’t checked yet.

sudo apt-get install fabric

What i have done is prepare my own EC2 AMI, where i have created a user and added my usual ssh-pubkey for simple authentication.
To do this you just have to start up an ubuntu AMI, log in to it and make your changes and then choose to make it into an AMI.
The ubuntu AMI i used is their official Maverick i386 AMI on us-east: ami-ccf405a5
You also have to change your default security group in EC2 to permit tcp port 22 or you won’t be able to connect to the machine.
The EC2 webservice require you to use their X509 certificate so you should create one of those and download the key and cert files.

Now let’s get to the code!

from libcloud.types import Provider
from libcloud.providers import get_driver
from libcloud.base import NodeImage, NodeSize
import os
from fabric.api import *
from fabric.contrib.console import confirm
import time
import string = True"/path/to/cert-BLABLA.pem")

EC2_SECRET_KEY = 'jghgfjhgfkjhgfuyrtgfhusdnsjkdf'

keyname = "your keyname"
username = "the user you created in the AMI"
my_ami = "ami-yourami"
i_size = "t1.micro" #This is what you should use if your using the Free Tier account

Driver = get_driver(Provider.EC2)
conn = Driver(EC2_ACCESS_ID, EC2_SECRET_KEY)

nodes = conn.list_nodes()

def all_instances():
        for node in nodes:
                if node.public_ip[0]:
                        print node.public_ip[0]
                        env.hosts += [username + "@" + node.public_ip[0]]

def new_instance():
        name = raw_input("Name of new instance: ")
        image = NodeImage(id=my_ami, name="", driver="")
        size = NodeSize(id=i_size, name="", ram=None, disk=None, bandwidth=None, price=None, driver="")
        node = conn.create_node(name=name, image=image, size=size, ex_keyname=keyname)
        nodes = conn.list_nodes()
        print nodes
        while nodes[-1].state != 0:
                print nodes[-1]
                nodes = conn.list_nodes()
        print "ok"
        nodes = conn.list_nodes()
        env.hosts = [username + "@" + nodes[-1].public_ip[0]]

def latest_instance():
        env.hosts = [username + "@" + nodes[-1].public_ip[0]]

Now write a small method for running “uname -a” in fabric:

def uname():
	run("uname -a")

This method can now be used in combination with any of the instance-methods:

fab all_instances uname
fab new_instance uname
fab latest_instance uname

The method new_instance will create a new instance from your AMI and when it’s ready connect via SSH and run your commands.
I have used a sleep-timer for 30 seconds to allow the new instance to boot up and start SSHd properly before we try to connect.
This timer have worked for my free account, but maybe you could have a lower value for faster machines as they will probably boot quicker.