DevOps Zone is brought to you in partnership with:

I enjoy programming in my free time and spend a considerable amount of time hacking away at open source projects as well as implementing those projects for various clients. My recent interests have included messaging (RabbitMQ specifically), Node.js, NoSQL, and alternative JVM languages such as Scala. You can also occasionally find me at several conferences speaking on some of my passions as well. Of course, got to balance all of this out with my wonderful baby girl and beautiful wife. James is a DZone MVB and is not an employee of DZone and has posted 20 posts at DZone. You can read more from them at their website. View Full User Profile

Dynamic Vagrant Nodes

03.19.2013
| 2239 views |
  • submit to reddit

I use vagrant a lot and at Zapier I use a setup where one Vagrantfile can be used to launch any instance in our infrastructure locally for testing. This is really quite useful as I can boot up a two node rabbitmq cluster with haproxy by simply typing vagrant up rabbitproxy01 rabbit01 rabbit02.

In the beginning this was a little messy as I just kept adding new node definitions and incrementing the ip address. But today I’ll share my refactored vagrant file for your own dynamic virtualizing goodness.

# -*- mode: ruby -*-
# vi: set ft=ruby :
domain = 'example.com'
 
# add your nodes here
nodes = ['puppet', 'rabbit', 'redis', 'http', 'jenkins', 'rabbitproxy']
 
 
puppet_nodes = []
subnet=10
nodes.each { |node_name|
  (1..10).each {|n|
    nodenum = "#{n}".rjust(2,'0')
    subnet += 1
    puppet_nodes << {:hostname => "#{node_name}#{nodenum}",  :ip => "172.16.32.#{subnet}", :box => 'precise64'} 
  }
}
 
# uncomment the below to see the ips for each host
# puppet_nodes.each { |n| puts "#{n[:hostname]} : #{n[:ip]}" }
 
Vagrant::Config.run do |config|
  puppet_nodes.each do |node|
    config.vm.define node[:hostname] do |node_config|
      node_config.vm.box = node[:box]
      node_config.vm.box_url = 'http://files.vagrantup.com/precise64.box'
      node_config.vm.host_name = "#{node[:hostname]}.#{domain}"
      node_config.vm.network :hostonly, node[:ip]
 
      if node[:fwdhost]
        node_config.vm.forward_port(node[:fwdguest], node[:fwdhost])
      end
 
      memory = node[:ram] ? node[:ram] : 256;
      node_config.vm.customize [
        'modifyvm', :id,
        '--name', node[:hostname],
        '--memory', memory.to_s
      ]
      
      node_config.vm.provision :puppet do |puppet|
          puppet.manifests_path = 'manifests'
          puppet.module_path = 'modules'
          puppet.manifest_file = 'site.pp'
      end
    end
  end
end

Essentially you just add your node names to nodes and when vagrant runs it will calculate a range of 10 host only ip addresses and node definitions for that node. So if you add “redis” to the list you can boot up redis01, redis02 … redis10.

Caveat: don’t just type vagrant up by itself or you’re going to have a bad time. This will essentially start bootstrapping many many vagrant boxes until your computer screams and falls over. Enjoy!

Published at DZone with permission of James Carr, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)