From 93482ade19c2f79bb172768cb2f4f93f10279d0b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 18 Dec 2018 18:41:57 +0100 Subject: [PATCH] Add cluster_members_addr parameter to specify ip addresses used in cluster setup Due to https://bugzilla.redhat.com/show_bug.cgi?id=1659389 we need to be able to specify the exact ip addresses being used in the cluster setup. This support exists also for corosync 2.x based systems, but seems to be quite a necessity when using corosync 3.x + knet. So let's add this feature in order to cover for the next Centos/RHEL release. Change-Id: I03d23177c7a913127ffc2f6d01a6318cb80d09c5 --- .../parser/functions/pcmk_cluster_setup.rb | 49 +++++++++++++++++++ manifests/corosync.pp | 14 +++++- spec/functions/pcmk_cluster_setup_spec.rb | 25 ++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 lib/puppet/parser/functions/pcmk_cluster_setup.rb create mode 100644 spec/functions/pcmk_cluster_setup_spec.rb diff --git a/lib/puppet/parser/functions/pcmk_cluster_setup.rb b/lib/puppet/parser/functions/pcmk_cluster_setup.rb new file mode 100644 index 00000000..e17dec2d --- /dev/null +++ b/lib/puppet/parser/functions/pcmk_cluster_setup.rb @@ -0,0 +1,49 @@ +module Puppet::Parser::Functions + newfunction( + :pcmk_cluster_setup, + type: :rvalue, + arity: -1, + doc: <<-eof +Input data cluster_members string separated by a space: +* String A space-separated string containing a list of node names +* String A list containing either a single string (single ip) or a list of strings + (multiple ipaddresses) associated to each cluster node + +Output forms: +* string - Output A string to be used in the cluster setup call to pcs + eof + ) do |args| + nodes = args[0] + addr_list = args[1] + fail "pcmk_cluster_setup: Got unsupported nodes input data: #{nodes.inspect}" if not nodes.is_a? String + fail "pcmk_cluster_setup: Got unsupported addr_list input data: #{addr_list.inspect}" if not addr_list.is_a? Array + node_list = nodes.split() + fail "pcmk_cluster_setup: node list and addr list should be of the same size when defined and not empty" if addr_list.size > 0 and addr_list.size != node_list.size + # If the addr_list was specified we need to return a string in the form of + # node1 addr=1.2.3.4 node2 addr=1.2.3.5 addr=1.2.3.6 node3 addr=1.2.3.7 + if addr_list.size > 0 + ret = '' + node_list.zip(addr_list).each do |node, ip| + # addr can be '1.2.3.4' or ['1.2.3.4', '1.2.3.5'] or + if ip.is_a? String + addr = "addr=#{ip}" + elsif ip.is_a? Array + addr = '' + ip.each do |i| + addr += "addr=#{i}" + addr += " " if not i.equal?(ip.last) + end + else + fail "pcmk_cluster_setup: One of the addresses in addr_list is neither a String nor an Array" + end + ret += "#{node} #{addr}" + ret += " " if not node.equal?(node_list.last) + end + # only node_list is specified so we just return the original string + else + ret = nodes.strip() + end + ret + end +end + diff --git a/manifests/corosync.pp b/manifests/corosync.pp index 370ed0be..e53d3cba 100644 --- a/manifests/corosync.pp +++ b/manifests/corosync.pp @@ -4,9 +4,18 @@ # # === Parameters # [*cluster_members*] -# (required) A space-separted list of cluster IP's or names to run the +# (required) A space-separted list of cluster IP's or names to run the # authentication against # +# [*cluster_members_addr*] +# (optional) An array of arrays containing the node addresses to be used +# As ring addresses in corosync (as required by corosync3+knet). For example: +# [[10.0.0.1], [10.0.0.10], [10.0.0.20,10.0.0.21]] with nodes [n1, n2, n3] +# will create the cluster as follows: +# pcs cluster setup clustername n1 addr=10.0.0.1 n2 addr=10.0.0.10 \ +# n3 addr=10.0.0.20 addr=10.0.0.21 +# Defaults to [] +# # [*cluster_members_rrp*] # (optional) A space-separated list of cluster IP's or names pair where each # component represent a resource on respectively ring0 and ring1 @@ -89,6 +98,7 @@ # class pacemaker::corosync( $cluster_members, + $cluster_members_addr = [], $cluster_members_rrp = undef, $cluster_name = 'clustername', $cluster_setup_extras = {}, @@ -207,7 +217,7 @@ class pacemaker::corosync( } if ! $cluster_members_rrp { - $cluster_members_rrp_real = $cluster_members + $cluster_members_rrp_real = pcmk_cluster_setup($cluster_members, $cluster_members_addr) } else { $cluster_members_rrp_real = $cluster_members_rrp } diff --git a/spec/functions/pcmk_cluster_setup_spec.rb b/spec/functions/pcmk_cluster_setup_spec.rb new file mode 100644 index 00000000..428fa70b --- /dev/null +++ b/spec/functions/pcmk_cluster_setup_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe 'pcmk_cluster_setup' do + context 'interface' do + it { is_expected.to run.with_params(123,[]).and_raise_error(Puppet::Error, /pcmk_cluster_setup: Got unsupported nodes input data/) } + it { is_expected.to run.with_params('foo', 'bar').and_raise_error(Puppet::Error, /pcmk_cluster_setup: Got unsupported addr_list input data/) } + it { is_expected.to run.with_params('n1 n2 n3', ['1', '2']).and_raise_error(Puppet::Error, /pcmk_cluster_setup: node list and addr list should be of the same size when defined and not empty/) } + it { is_expected.to run.with_params('n1 n2 n3', ['1', ['2'], nil]).and_raise_error(Puppet::Error, /pcmk_cluster_setup: One of the addresses in addr_list is neither a String nor an Array/) } + end + + it 'returns the original node string when no addresses are specified' do + is_expected.to run.with_params('n1 n2 n3', []).and_return('n1 n2 n3') + is_expected.to run.with_params('n1 n2', []).and_return('n1 n2') + is_expected.to run.with_params('n1', []).and_return('n1') + is_expected.to run.with_params('n1 ', []).and_return('n1') + end + + it 'returns the correct cluster setup cmd given both nodes and ip address' do + is_expected.to run.with_params('ctr-0 ctr-1 ctr-2', ['1.1.1.1', '2.2.2.2', '3.3.3.3']).and_return('ctr-0 addr=1.1.1.1 ctr-1 addr=2.2.2.2 ctr-2 addr=3.3.3.3') + is_expected.to run.with_params('ctr-0 ctr-1', ['1.1.1.1', ['2.2.2.2', '3.3.3.3']]).and_return('ctr-0 addr=1.1.1.1 ctr-1 addr=2.2.2.2 addr=3.3.3.3') + is_expected.to run.with_params('ctr-0', [['2.2.2.2', '3.3.3.3', '4.4.4.4']]).and_return('ctr-0 addr=2.2.2.2 addr=3.3.3.3 addr=4.4.4.4') + is_expected.to run.with_params('ctr-0 ctr-1 ctr-2', [['1.1.1.1'], ['2.2.2.2'], '3.3.3.3']).and_return('ctr-0 addr=1.1.1.1 ctr-1 addr=2.2.2.2 ctr-2 addr=3.3.3.3') + is_expected.to run.with_params('ctr-0 ctr-1 ctr-2', [['1fe80::7ed:a95d:ed26:f5b', 'fe80::7ed:a95d:ed26:f5c', 'fe80::7ed:a95d:ed26:f5d'], ['1.1.1.1', '2.2.2.2'], '3.3.3.3']).and_return('ctr-0 addr=1fe80::7ed:a95d:ed26:f5b addr=fe80::7ed:a95d:ed26:f5c addr=fe80::7ed:a95d:ed26:f5d ctr-1 addr=1.1.1.1 addr=2.2.2.2 ctr-2 addr=3.3.3.3') + end +end