Broham: A simple, global, highly-available, none-too-bright service registry.

Broham always knows where his bros are, bro! Using broham, a newly-created cloud machine can annouce its availability for a certain role (“nfs_server” or “db_slave-2”), allowing any other interested nodes to discover its public_ip, private_ip, etc.

It uses Amazon’s SimpleDB service, so the registry is global, highly-available, secure, accessible from any programming language (or even curl if you’re clever), and simple. As for Broham himself, he fills out a suit OK but isn’t too bright: there’s no monitoring or logging, for instance.

Broham plays nicely with Chef and indeed was written to coordinate node assignment for a hadoop cluster chef setup.

Examples:


  require 'broham'
  Settings.access_key_id     = 'XXXXXXXXXX'
  Settings.secret_access_key = 'XXXXXXXXXX'

  # create a context for the 'chad' cluster
  class Chad < Broham::Cluster ; end
  Chad.establish_connection
  Chad.create_domain

  # On NFS server start, register an nfs share
  Chad.register_nfs_share '/home'
  #=> #<Chad @attributes={"timestamp"=>["20100405072638"], "client_path"=>["/home"], "server_path"=>["/home"], "role"=>["nfs_server"], "public_ip"=>["250.249.248.247"], "private_ip"=>["192.168.69.22"], "default_ip"=>["192.168.69.22"]}
  # On the nfs clients, get the local IP and server-side path of the share, ready to insert into /etc/fstab
  Chad.nfs_device_path 
  #=> "192.168.69.22:/home"

  # Register as one of many nodes with a given role
  Chad.register_as_next 'dj'
  #=> #<Chad @attributes={"timestamp"=>["20100405072931"], "role"=>["dj-1"], "idx"=>["1"], "default_ip"=>["192.168.69.10"], "public_ip"=>["250.249.248.247"], "private_ip"=>["192.168.69.10"]}
  
  # Find the highest-yet-registered node in the 'dj' role and immediately
  # register as the next one. Even if a thundering herd of hosts try to register
  # in this role, Broham will ensure that exactly one host claims each index.
  Chad.host('dj') ; Chad.register_as_next 'dj'
  #=> #<Chad @attributes={"timestamp"=>["20100405073626"], "role"=>["dj"], "idx"=>["2"], "default_ip"=>["192.168.69.14"], "public_ip"=>["250.249.248.247"], "private_ip"=>["192.168.69.14"]}]
  #=> #<Chad @attributes={"timestamp"=>["20100405073626"], "role"=>["dj-4"], "idx"=>["4"], "default_ip"=>["192.168.69.22"], "public_ip"=>["250.249.248.247"], "private_ip"=>["192.168.69.22"]}]

Alternate interface:


  Chad.yo! 'beer-stand'
  #<Chad @attributes={"timestamp"=>["20100405071446"], "role"=>["beer-stand"], "public_ip"=>["250.249.248.247"], "private_ip"=>["10.0.69.69"]}

  Chad.sup? 'beer-stand'
  #<Chad @attributes={"timestamp"=>["20100405071446"], "role"=>["beer-stand"], "public_ip"=>["250.249.248.247"], "private_ip"=>["10.0.69.69"]}

Commandline Interface


  $ broham-register chad nfs_server --set-server_path=/home --set-client_path=/home
  Registering as nfs_server in chad cluster, with {:server_path=>"/home", :client_path=>"/home"}
  {"timestamp":["20100405093238"],"fqdn":["nfs.infochimps.org"],"client_path":["/home"],"server_path":["/home"],"role":["nfs_server"],"private_ip":["10.123.156.231"],"default_ip":["10.123.156.231"],"public_ip":["104.136.251.50"]}

  $ broham-host chad nfs_server
  {"timestamp":["20100405093238"],"fqdn":["nfs.infochimps.org"],"client_path":["/home"],"server_path":["/home"],"role":["nfs_server"],"private_ip":["10.123.156.231"],"default_ip":["10.123.156.231"],"public_ip":["104.136.251.50"]}

  # Alternative interface works too.
  $ broham-sup chad nfs_server
  {"timestamp":["20100405093238"],"fqdn":["nfs.infochimps.org"],"client_path":["/home"],"server_path":["/home"],"role":["nfs_server"],"private_ip":["10.123.156.231"],"default_ip":["10.123.156.231"],"public_ip":["104.136.251.50"]}

  $ broham-unregister-all chad nfs_server
  Removing nfs_server from chad cluster
  {"timestamp":["20100405093238"],"fqdn":["nfs.infochimps.org"],"client_path":["/home"],"server_path":["/home"],"role":["nfs_server"],"private_ip":["10.123.156.231"],"default_ip":["10.123.156.231"],"public_ip":["104.136.251.50"]}

  # Alternative interface:
  broham-sup host               # show host
  broham-sup_yall hosts         # show all hosts matching the given (start-of-string-anchored) regex
  broham-yo host                # register as given host
  broham-diss host              # unregister given host
  broham-fuck_all_yall hosts_re # unregister all hosts matching the given (start-of-string-anchored) regex

IRB Usage


    require 'configliere'
    Settings.read('broham.yaml')
    require 'broham'
    require 'broham/script'
    Broham.establish_connection

    Broham.unregister_like 'gibbon-slave'

Setup

For setup, we recommend configliere


  require 'configliere'
  Configliere.use :config_file
  Settings.read 'broham.yaml'; Settings.resolve!

Like Broseph Stalin, you are leading the way to the dictatorship of the broletariate. It is truly revbrolutionary. Like the Bro v. Wade of our generation. You brobliterate the enemy from the very peak of Mt. Brolympus. That’s some shit. That’s brolific. But that’s the kind of bro you are. — Zach Caldwell

Warnings!

Make sure you are using a recent (>= 1.11,0) version of right_aws, and set the SDB_API_VERSION environment variable to ‘2009-04-15’:


  export SDB_API_VERSION='2009-04-15'

For register_as_next, you’ll need a version of right_aws that supports conditional puts: http://github.com/mrflip/right_aws

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don’t break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright © 2010 Philip (flip) Kromer. See LICENSE for details.