So here is my use case, I have a two nodes which have to be configured to know about each other, but I can’t use multicast, and I want to be elastic, in that I can add a node and the others configs get updated. So to start we are going to have two nodes, gateway1 and gateway2, and each has a config file called sipmethod.xml which contains a node of XML data that defines the cluster.

<Cluster>
   <Node name="gateway2" local="10.72.111.116:47520">
      <Peer remote="10.110.234.150:47520"/>
   </Node>
 </Cluster>

and here is my template that creates this section (sorta):

<% if node[:prism][:sipmethod][:cluster] %>
 <Cluster>
   <Node name="<%=node[:hostname]%>" local="<%=node[:ipaddress]%>:<%= node[:prism][:sipenv][:rmi_port] %>">
     <% search(:node, "role:rayo_gateway AND chef_environment:#{node.chef_environment}").each do |peer| %>
      <Peer remote="<%= (peer.ec2 ? peer.ec2.local_ipv4 : peer.ipaddress) %>:<%= node[:prism][:sipenv][:rmi_port] %>"/>
     <%end%>
   </Node>
 </Cluster>
 <%end%>

Now there is one problem with this approach, if you look carefully the peers are going to include itself, which is not going to work.

<Cluster>
   <Node name="gateway2" local="10.72.111.116:47520">
      <Peer remote="10.110.234.150:47520"/>
      <Peer remote="10.72.111.116:47520"/>  <!-- PROBLEM -->
   </Node>
 </Cluster>

I need to not include the node running the search in the results, and this is actually pretty simple:

We are going to take this search and simply add a NOT clause:

search(:node, "role:rayo_gateway AND chef_environment:#{node.chef_environment} NOT name:#{node.name}")

This will result in returning every gateway in my environment except the one running the search, and the end result is the dynamically configured cluster config:

<Cluster>
   <Node name="gateway2" local="10.72.111.116:47520">
      <Peer remote="10.110.234.150:47520"/>
   </Node>
 </Cluster>

johntdyer

John T Dyer