Showing posts with label cloud-init. Show all posts
Showing posts with label cloud-init. Show all posts

Thursday, January 6, 2011

Cloud LAMP Stack in 60 seconds

Need to setup a LAMP development or test environment ? on the cloud ? Ubuntu server ? Think it's hard ? Think again! See me setup a LAMP stack, get wordpress up and running in less seconds than most people can eat a sandwich! Check out this video



If you'd like to download the cloud-init file used, as well as other similar files, visit the awstrial project

Monday, January 3, 2011

Advanced cloud-init custom handlers

I love cloud-init, the Ubuntu cloud technology that enables a cloud instance to bootstrap itself and customize itself into whatever you want it to be (coming from a generic image). I had previously created a screencast introducing cloud-init, and written an article on running cloud-init locally over KVM. This time however, I demonstrate some advanced cloud-init foo, namely how to write a custom content handler in python. Pass the code and data over the cloud's user-data, and watch your code crunch on the data. The possibilities are endless, using this technique you are basically writing plugins for cloud-init allowing you to do almost anything. Ok, enough babbling, let's do some cool stuff

We need the "write-mime-multipart" script from cloud-init. I would not recommend installing cloud-init on your own machine, since cloud-init is designed to be run on cloud instances (not physical nodes). If you do install it on your own machine, it blocks the boot process waiting for the cloud userdata service to appear (which it never does), so you end up waiting a lot! To get the script, we just check out the code directly
bzr branch lp:cloud-init

You'll find that script in the tools/ directory. Assuming you could run cloud-init on local KVM, we now need to replace the user-data file, which in the previous article was written using cloud-config syntax, with a new file. The new user-data file is a multipart file composed of custom python code and data you want your python code to chew on! Here is how you create the file
./write-mime-multipart --output user-data part-handler.txt one:text/plain two:text/plain

Let's take a look at the contents of those files. Files "one" and "two" are the data, while "part-handler.txt" is the python code adapted from cloud-init. In our case, I chose to let our part handler be a "user-creation" provider, i.e. you supply a list of user names in the data file, the code loops over them creating them. Simple enough for an example I hope. Let's check out the data files
$ cat one
jhonny
cash
$ cat two 
agent
smith

These two files hold the 4 users to be created! I split them into 2 files, just to demo you could have multiple input files. Now let's check out the code living in part-handler.txt
#part-handler
# vi: syntax=python ts=4

def list_types():
    # return a list of mime-types that are handled by this module
    return(["text/plain", "text/go-cubs-go"])

def handle_part(data,ctype,filename,payload):
    # data: the cloudinit object
    # ctype: '__begin__', '__end__', or the specific mime-type of the part
    # filename: the filename for the part, or dynamically generated part if
    #           no filename is given attribute is present
    # payload: the content of the part (empty for begin or end)
    if ctype == "__begin__":
       print "my handler is beginning"
       return
    if ctype == "__end__":
       print "my handler is ending"
       return

    print "==== received ctype=%s filename=%s ====" % (ctype,filename)
    import os
    for user in payload.splitlines():
        print " == Creating user %s" % (user)
        os.system('sudo useradd -p ubuntu -m %s' % (user) )
    print "==== end ctype=%s filename=%s" % (ctype, filename)

Most of the code is just boiler plate. The code needs to implement two functions "list_types()" that returns a list of content types that this code can handle. In our case, we return "text/plain" and "text/go-cubs-go". Note that when we ran "write-mime-multipart" we used the mime type text/plain, and that is the reason cloud-init would invoke this code to handle it. Because the code advertises it can handle text/plain types. The second function the code needs to implement is handle_part. This is called at the very beginning and very end for initialization and tear-down. It is also called on each input file (2 times in our case). A sample run looks like

qemu-cloud-init-advanced
and sure enough, the 4 users were created
qemu-cloud-init-users-created

That should be everything you need to know about writing custom mime type handlers as extensions to cloud-init. Indeed that is some pretty amazing stuff! Any questions or comments, leave a comment

Thursday, December 30, 2010

Cloud Instance with Cloud-Init on KVM

I wanted to run an Ubuntu server cloud instance locally on KVM hypervisor. I also wanted to run cloud-init on the local setup in order to experiment a bit with it. So that means, downloading a UEC image, booting it under KVM, and passing cloud-init parameters to it as it boots. Much to my surprise things were far easier than I expected, all thanks to our rocking Ubuntu cloud team. Here's the script I cobbled together, most of it is basically a rip off from this UEC Images wiki page.

So what this does is, it:
  • Downloads a UEC image of natty server daily i386 if it doesn't exist
  • Sets a few variables
  • Creates a qcow disk image, shadowing/cowing/differencing the downloaded image. This is to keep the originally downloaded image pristine
  • Downloads some sample user-data and meta-data (warning, this runs arbitrary commands and injects keys inside your VM, only use for testing!). To experiment with cloud-init you'd have to modify the user-data to your liking
  • Runs a local simple webserver (port 8000)
  • Boots the cow image in a local kvm. As it boots, you'll notice on your terminal the following two requests being made "GET /meta-data" and "GET /user-data". Cloud-init uses this data to customize the image as it boots
  • Once you close kvm, kills the web-server
So all you need to do, is create an empty directory, put this script in it and run it
uecnattyservercurrent=http://uec-images.ubuntu.com/server/natty/current/natty-server-uec-i386.tar.gz
tarball=$(basename $uecnattyservercurrent)
[ -f ${tarball} ] || wget ${uecnattyservercurrent}
contents=${tarball}.contents
tar -Sxvzf ${tarball} | tee "${contents}"
cat natty-server-uec-i386.tar.gz.contents
base=$(sed -n 's/.img$//p' "${contents}")
kernel=$(echo ${base}-vmlinuz-*)
floppy=${base}-floppy
img=${base}.img
qemu-img create -f qcow2 -b ${img} disk.img
wget http://smoser.brickies.net/ubuntu/uec-seed/meta-data
wget http://smoser.brickies.net/ubuntu/uec-seed/user-data
python -m SimpleHTTPServer &
websrvpid=$!
kvm -drive file=disk.img,if=virtio,boot=on -kernel "${kernel}" -append "ro init=/usr/lib/cloud-init/uncloud-init root=/dev/vda ds=nocloud-net;s=http://192.168.122.1:8000/ ubuntu-pass=ubuntu"
kill $websrvpid

Wednesday, December 8, 2010

Introducing Ubuntu Cloud-Init Technology

Ubuntu Cloud-init is an awesome piece of software that helps Ubuntu run as great as it does on the cloud. Cloud-init kicks in as the server boots, and starts converting your server from the generic template it has been started from, into the server image you need. Coupled with the easy to use cloud-config syntax, it's just so easy and quick getting this rolling. Check out this screencast, where I introduce cloud-init and demo what it can be used for



Questions ? Comments ? I'm all ears, leave me a note in the comments section and I'll reply back
Want to create your own screencasts (it's real easy), ping me (kim0 on irc) and I'll be sure to help you publish them

Friday, October 15, 2010

OpenWeek Introduction to Cloud IRC session logs

If you couldn't attend the Ubuntu Open Week session live on IRC, don't despair! You can read the logs at
http://irclogs.ubuntu.com/2010/10/13/%23ubuntu-classroom.html#t17:01