A collection of computer systems and programming tips that you may find useful.
 
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Tuesday, January 27, 2009

AWS EC2 ec2-bundle-vol and Ruby problem

When you want to bundle an image on an Amazon Web Services EC2 node you run the 'ec2-bundle-vol' script. This is a Ruby script that performs all sorts of magic.

Be aware of the following problem if you install your own version of Ruby

I'm running a Fedora Core 8 node and the latest version of Ruby that I can get using the yum updater is 1.8.6 - but I want 1.8.7 - so I installed from source into /usr/local/bin. I have /usr/local/bin ahead of /usr/bin in my path so I get to see the 1.8.7 version and I can leave the old version alone.

But when I try to bundle an EC2 image I get this:
# ec2-bundle-vol
/usr/lib/site_ruby/ec2/amitools/bundlevol.rb:11:in `require': no such file to load -- ec2/amitools/bundle (LoadError)


The problem appears to be tied to the new version. I can fix it by temporarily changing my path so that I pick up the 1.8.6 version of Ruby
# PATH=/usr/bin:$PATH

And now the command works... of course you will need to run the command with your certificates etc. You will probably see a verbose message about rsync exiting with an error code - ignore it.

Follow that with a call to ec2-upload-bundle

Make sure you reset your path after this so you can get the latest version of Ruby. I guess you can also rename /usr/bin/ruby (1.8.6) and then symlink in the 1.8.7 version.

I have so many issues with installing separate versions of ruby on Mac and Linux systems. All I really want to do is be able to upgrade the default installation to the latest version. Not sure why that is so difficult with yum, etc.

Monday, January 19, 2009

Setting up the Starling Messaging Server

Starling is a simple messaging server for distributed queuing. It was written by Blaine Cook and colleagues at Twitter and is used extensively by them. It has been released as open source and is becoming widely used. It is written entirely in Ruby and uses the memcache protocol for communication.

I am looking at it as a simple way to manage distributed tasks on my local network. The basic idea is similar to other queuing systems like Amazon's SQS. It has benefits and disadvantages compared to other systems. The benefits for me are that it is simple to set up and use.

The basic idea is that you run a Starling server on one machine, listening on a specific address and port. Other machines can set or get messages from an arbitrary number of queues on the server. It should be used on a trusted network as it has no security.

Fetch the latest version as a rubygem from github at http://github.com/starling/starling/tree/master. You will also need the fiveruns-memcache-client (at least as of Jan 2009)

$ gem sources -a http://gems.github.com/
$ sudo gem install fiveruns-memcache-client
$ sudo gem install starling-starling


This should also install the eventmachine gem for you if needed.
NOTE I have not been able to install the eventmachine gem on Fedora 7 because of some problem finding -lruby. I think it has to do with having lib and lib64. Anyone got a fix for that?

The gem has two components - a starling executable that implements the server and the ruby library that you use to interact with it.

You need to copy the executable out of the gem directory. The default gem directory on Ubuntu is /var/lib/gems/1.8/gems and on (my) Mac OS X it is /usr/local/lib/ruby/gems/1.8/gems/. The current version is installed under starling-starling-0.9.9

I'm just going to cover the Ubuntu installation here:

$ sudo cp /usr/local/lib/ruby/gems/1.8/gems/starling-starling-0.9.9/bin/starling /usr/local/bin/starling
$ sudo cp /usr/local/lib/ruby/gems/1.8/gems/starling-starling-0.9.9/bin/starling_top /usr/local/bin/starling_top


I had to edit the first line of both of these Ruby scripts to point to where my Ruby interpreter was installed (#!/usr/bin/env ruby)

Test out the installation by running the server as root
# starling
This will start up a server on the default address of 127.0.0.1 and port 22122

To have the server run as system start:
1: Copy the example init script from the gem etc directory.
$ sudo cp /usr/local/lib/ruby/gems/1.8/gems/starling-starling-0.9.9/etc/starling.ubuntu /etc/init.d

2: Edit the file to change the user and group to root. This is not ideal. You should create a starling user and group but I have not been able to get this to work - probably just a permissions issue - any fixes to this are welcomed. You also need to change the IP address on which to run the service from the default of 0.0.0.0
DUSER=root
DGROUP=root
LISTEN=192.168.1.1

3: Create the log directory /var/log/starling
Look at the contents of /var/log/starling/starling.log if you have problems.

4: Create the spool directory /var/spool/starling that starling uses to back up its queues. Each queue will get a separate binary file. Poke around in the contents of these using 'od -c ' if you are so inclined. (Starling may create this automatically - but it does NOT create the log directory)

5: Start/stop the server
# /etc/init.d/starling start

6: Set up the appropriate symlinks in the /etc/rc* directories. On Fedora I would use chkconfig for this but it barfs on Ubuntu for me. Setting them manually I created K08starling in rc0.d, rc1.d and rc6.d and S92starling in rc3.d, rc4.d, rc5.d and rc6.d

To use Starling to manage messages you will use the Ruby client library. The interface is refreshingly simple. Test it out using irb:
$ irb --simple-prompt
>> require 'rubygems'
=> true
>> require 'starling'
=> true
>> star = Starling.new('192.168.1.1:22122')
=> <MemCache: 1 servers, 1 buckets, ns: nil, ro: false>
>> star.available_queues()
=> []
>> star.set('myqueue', 'Hello World')
=> nil
>> star.available_queues()
=> ["myqueue"]
>> star.sizeof('myqueue')
=> 1
>> msg = star.get('myqueue')
=> "Hello World"


Note that the Starling.new call makes a connection to the server which should already be running. It does not itself start a server. Also note that a call to get() when there are no messages in the queue will just hang waiting for the next message. So check first with sizeof(queue) if you don't want that to happen.

There are no hard and fast limits as to how large messages can be, unlike Amazon SQS. But I would imagine that very large messages are going screw up your performance. Remember this is using a memcache-like architecture and so memory can become limiting. Starling is designed to handled lots of small messages so it's probably best to use it in this way.

Starling is written entirely in Ruby. The documentation for the gem is reasonable. Look at the code in the gem if you need to really understand what is going on.

To use Starling within Rails applications you should look at the Workling plugin


Wednesday, January 7, 2009

Ruby and the RubyInline gem

I wanted to transfer a Ruby app that used the Inline gem to a Linux machine and had trouble getting it to work. Here are the steps needed to make it work.

The ruby code uses the Inline gem which allows you to write inline C code in your application for better performance. The code itself includes this line:
require "inline"

In transferring it to a new machine (linux in this case - Fedora and Ubuntu machines in fact) I would get the error "undefined method 'inline'".

I figured this meant I did not have the 'inline' gem so I ran 'sudo gem install inline'. But after that I still got the same error... WRONG GEM! I finally figured out that I want to install RubyInline not inline... plus you also need the hoe gem
$ sudo gem install RubyInline
$ sudo gem install hoe


Tried running the app and this time I got:
ERROR: Can't find header dir for ruby, Exiting...

This tells me that I need a development version of Ruby with all the header files. A regular ruby install does not give you this.

On Mac OS X you need to install the Xcode developer tools.
On Ubuntu you need to do this:
$ sudo apt-get install ruby-dev
On Fedora you would do:
$ sudo yum install ruby-devel

Try it once more and it should work!

Friday, January 2, 2009

CSS, Tables and Borders

This post deals with an issue that can arise if you are trying to render a table in HTML in which you have varying numbers of cells per row.

Ideally all rows should have the same number of cells, but sometimes that would involve ugly code in order to pad out the html. The browsers can handle the case so why not let them?

But a problem arises when you want to draw a border around the whole table. For this you would add this sort of style to your table tag:
table {
border: 1px solid #000;
border-collapse: collapse;
}


This works fine in Firefox on Mac OS X, but in Safari the border is not drawn for any 'missing' cells.

You can fix this by adding a tbody tag and giving it the attribute
tbody {
display: block;
}


This acts to define that table as a rectangular 'block' of pixels, as opposed to some irregular shape, and then it draws the border around that - that's my interpretation of it anyway.

You can get the border by setting the display attribute in the table tag and removing the tbody tag but the size of the table may be different. In general you want to use tbody tags, for this reason and in order for ajax/dom manipulation reasons.

And always, always test your pages out on all the main browsers before deploying!

Archive of Tips