Vagrant + Multiple Machines + Ansible

Hi

I’m trying to write playbook to deploy automatically a Galera Cluster. I’ve been googling before ask help and I found some interesting info about Vagrantfile and multi machine scenario.

My main problem is until now I have never worked with vagrant multiple machines (3 nodes) and Ansible. I just want to deploy 3 nodes with Vagrant and then make the provision with Ansible. My current code does well the easies part of the work

the problem I have is I don’t know how set some variables into my.cnf.j2 jinja template

wsrep_node_address = {{ ansible_eth1.ipv4.address }}

bind_address = {{ galera_conf[‘bind_address’] }}

for example, I have no problem with this two variables, one is a fact and other I have it on defaults/main.yml but what about this one?

wsrep_cluster_address = gcomm://ip1,ip2,ip3

I just don’t know how to setup this parameter. Do I have to use groups of inventory file? Where I can find the values of my galera cluster nodes? From inventory? From Vagrantfile? And how I can make to ansible write it in a right way?

Thanks

If you use a group in the inventory file, e.g. named 'cluster', then
your template could contain something like this:

wsrep_cluster_address=gcomm://{% for host in groups['cluster'] %}{% if not loop.first %},{% endif %}{{ hostvars[host]['wsrep_node_address'] }}{% endfor %}

Hope this helps

First, see the “Tips and Tricks” section here about using ansible with parallel execution in Vagrant: http://docs.vagrantup.com/v2/provisioning/ansible.html. You’ll need to do the provisioning this way to properly collect facts on all the machines.

Let’s say you had a group called “cluster” that contained servers 1, 2, and 3. To generate the variable for wsrep_cluster_address, you would have to do something like:

`
{% set iface = ‘ansible_eth1’ %}

wsrep_cluster_address = gcomm://{% for server in groups[“cluster”] %}{{ hostvars[server][iface].ipv4.address }}{% if not loop.last %},{% endif %}{% endfor %}
`

The first line I’m setting a a jinja2 variable of the interface that holds the IP I want to use, just for convenience. The second line is the magic – I’m doing a for loop through my cluster inventory group, and for each host I’m printing the interface, separating each IP by a comma unless it’s the last host, then I don’t want to use a comma.

  • James

Hi guys

thanks a lot, I’d never been able to reach this solution without help. I will try to put all this together to see if it works and update post as soon as possible!

Thanks again

Hi!

wow, I was reading about the subject of dynamic inventory. Actually it is my first time with a setup so complex. My Vagrantfile is (based on work of one guy, I don’t remember now the link of github, apologies):

# -- mode: ruby --
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don’t touch unless you know what you’re doing!
VAGRANTFILE_API_VERSION = “2”

cluster = {
“node1” => { :ip => “192.168.33.50”, :cpus => 1, :mem => 1024 },
“node2” => { :ip => “192.168.33.51”, :cpus => 1, :mem => 1024 },
“node3” => { :ip => “192.168.33.52”, :cpus => 1, :mem => 1024 },
}

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = “nrel/CentOS-6.5-x86_64”
config.vm.box = “ubuntu/precise64”

cluster.each_with_index do |(hostname, info), index|
config.vm.define hostname do |cfg|
cfg.vm.provider :virtualbox do |vb, override|
config.vm.box = “ubuntu/precise64”
override.vm.network :private_network, ip: “#{info[:ip]}”
override.vm.hostname = hostname
vb.name = ‘pxc-’ + hostname
vb.customize [“modifyvm”, :id, “–memory”, info[:mem], “–cpus”, info[:cpus], “–hwvirtex”, “on” ]

end # end provider

# provision nodes with ansible
if index == cluster.size - 1
cfg.vm.provision :ansible do |ansible|
ansible.verbose = “vvvv”
ansible.extra_vars = { ansible_ssh_user: ‘vagrant’ }
ansible.inventory_path = “./inventory”
ansible.playbook = “playbook.yml”
ansible.limit = “local”
end # end provision
end #end if

end # end config

end # end cluster

end # end vagrant

I don’t know if it is the better way to do it, but at least it is the only one that worked for me. I run a loop to provision all machines and then I run playbook.yml.

Then in my inventory I have:

[local]
node1 ansible_ssh_host=192.168.33.50
node2 ansible_ssh_host=192.168.33.51
node3 ansible_ssh_host=192.168.33.52

son in my template I finally wrote:

% set iface = ‘ansible_eth1’ %}
wsrep_cluster_address = gcomm://{% for server in groups[“local”] %}{{ hostvars[server][iface].ipv4.address }}{% if not loop.last %},{% endif %}{% endfor %}

And worked perfectly!

Thanks a lot guys!