Deploying Ubuntu on Rackspace using Fog and Cloud-Init

This post is an amalgamation of Vladimir Vuksan’s Provision to cloud in 5 minutes using fog (EC2-specific) and Jeff Gran’s Bootstrapping an Ubuntu Server on Rackspace Using Cloud-Init and Fog – I contributed little more than (inexpertly) gluing them together.

Assuming you already have the Fog gem installed:

First, as a prerequisite and as Jeff Gran notes, you’ll need to create a Rackspace image with the cloud-init package installed.

Next, similar to what Vladimir Vuksan describes, create a config.rb file, and populate the following values as appropriate for your environment:

#!/usr/bin/env ruby

@flavor_id = 3
@image_id = 1234567

@rackspace_username =  'example'
@rackspace_api_key = '1234....'

@private_key_path = './ssh/id_rsa'
@public_key_path = './ssh/id_rsa.pub'

The flavor_id values and image_id specify the instance size and the image you built with cloud-init installed (see the “fog” executable’s “Compute[:rackspace].flavors” and “Compute[:rackspace].images”, respectively); the Rackspace username and api_key can be retrieved from within the console under “Your Account: API Access.” The SSH key pair will be what you use to access the new instance as root.

Third, create a cloud-init user_data file ERB template; place it in ./cloud-init/user_data.erb; for example:

#cloud-config
apt_upgrade: true
hostname: <%= hostname %>

packages:
- emacs
- git
- puppet

#runcmd:

#ssh_keys:
#  rsa_private: |
#  rsa_public:
#  dsa_private: |
#  dsa_public:

Finally, the script you launch to deploy Rackspace images is as follows:

#!/usr/bin/env ruby

# Based on:
# http://blog.vuksan.com/2010/07/20/provision-to-cloud-in-5-minutes-using-fog/
# as well as:
# http://jeffgran.com/276/blog/ubuntu-cloud-init-rackspace-fog-ruby

require 'erb'
require 'optparse'

require 'rubygems'

require 'fog'
require 'mime'

# Parse options:
options = {}

optparse = OptionParser.new do|opts|
  opts.banner = "Usage new_instance.rb [options]"

  options[:name] = 'rax.example.com'
  opts.on( '-n', '--name INSTANCE_NAME', 'Instance name (default: rax.example.com)' ) do|n|
    options[:name] = n || 'rax.example.com'
  end

  options[:user_data] = './cloud-init/user_data.erb'
  opts.on( '-u', '--userdata USER_DATA', 'Path to Cloud-Init user_data ERB template (default: ./cloud-init/user_data.erb)' ) do |u|
    options[:user_data] = u || './cloud-init/user_data.erb'
  end

  opts.on( '-h', '--help', 'Display this help message' ) do
    puts opts
    exit
  end
end

optparse.parse!

hostname = options[:name] # to facilitate erb cloud-init template

# Create cloud-init data:

f = File.new(options[:user_data])
e = ERB.new(f.read)
user_data = MIME::MultipartMedia::Mixed.new
user_data.add_entity(MIME::TextMedia.new(e.result, 'text/plain'))

# Import Rackspace credentials:
require './config.rb'

# Connect to Rackspace:
connection = Fog::Compute.new({ 
  :provider           => 'Rackspace',
  :rackspace_api_key  => @rackspace_api_key, 
  :rackspace_username => @rackspace_username
})

# Launch instance:
puts "Launching instance '#{options[:name]}'..."

server = connection.servers.bootstrap({
  :flavor_id        => @flavor_id,
  :image_id         => @image_id,
  :name             => hostname,
  :personality      => [ { 'path'     => '/var/lib/cloud/seed/nocloud-net/user-data',
                           'contents' => user_data.to_s }, 
                         { 'path'     => '/var/lib/cloud/seed/nocloud-net/meta-data',
                           'contents' => ' ' } ],
  :private_key_path => @private_key_path,
  :public_key_path  => @public_key_path
})

puts "Instance launched at #{server.public_ip_address()}"

Launch it with the “-h” flag to see usage; otherwise, launch it with no arguments to launch an instance with your default options.

3 thoughts on “Deploying Ubuntu on Rackspace using Fog and Cloud-Init”

  1. I actually opened a ticket about this; apparently it’s a “known issue that has been occuring since [Rackspace's] recent deployment [of] Xen Server technology” but they consider it “an infrastructural problem that isn’t necessarily a show-stopper” with no official estimate of resolution. (I was told it might be “solved or worked-around before January.”)

Comments are closed.