Initial pcs 0.10 support
pcs 0.10 has changed a few things around cluster authentication so we need to parametrize things depending on the pcs version on the system. We also make sure that if you use the cluster_members_addr parameter it stays compatible with pcs 0.9 by only returning the node names and not the nodenames + addr=... strings. Tested this on a standalone env with pcs 0.10 (rhel8os + f28 containers no pre-installed pcs rpm) and on an OSP14 using pcs 0.9 Change-Id: I8693cc0fdd51be155273e0dba8bc14b3db79ba8d
This commit is contained in:
parent
584d478314
commit
c7b21ee0cb
|
@ -1,3 +1,5 @@
|
|||
require_relative '../../provider/pcmk_common'
|
||||
|
||||
module Puppet::Parser::Functions
|
||||
newfunction(
|
||||
:pcmk_cluster_setup,
|
||||
|
@ -8,6 +10,7 @@ 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
|
||||
* String the version of pcs used
|
||||
|
||||
Output forms:
|
||||
* string - Output A string to be used in the cluster setup call to pcs
|
||||
|
@ -15,35 +18,45 @@ Output forms:
|
|||
) do |args|
|
||||
nodes = args[0]
|
||||
addr_list = args[1]
|
||||
pcs_version = args[2]
|
||||
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
|
||||
fail "pcmk_cluster_setup: Got unsupported version input data: #{pcs_version.inspect}" if not pcs_version.is_a? String
|
||||
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)
|
||||
# pcs 0.10 supports knet clusters which require addresses to be specified
|
||||
if pcs_version =~ /0.10/
|
||||
# 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
|
||||
else
|
||||
fail "pcmk_cluster_setup: One of the addresses in addr_list is neither a String nor an Array"
|
||||
ret += "#{node} #{addr}"
|
||||
ret += " " if not node.equal?(node_list.last)
|
||||
end
|
||||
ret += "#{node} #{addr}"
|
||||
ret += " " if not node.equal?(node_list.last)
|
||||
# only node_list is specified so we just return the original string
|
||||
else
|
||||
ret = nodes.strip()
|
||||
end
|
||||
# only node_list is specified so we just return the original string
|
||||
ret
|
||||
elsif pcs_version =~ /0.9/
|
||||
# With pcs 0.9 only non-knet clusters are supported, aka only one address can be used
|
||||
# so we take the node name as we always did
|
||||
nodes.strip()
|
||||
else
|
||||
ret = nodes.strip()
|
||||
fail("pcmk_cluster_setup: pcs #{pcs_version} is unsupported")
|
||||
end
|
||||
ret
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -26,6 +26,19 @@ else
|
|||
TIMEOUT_BIN = '/usr/bin/timeout'
|
||||
end
|
||||
|
||||
# Use pcs_cli_version() as opposed to a facter so that if the pcs
|
||||
# package gets installed during the puppet run everything still works
|
||||
# as expected. Returns empty string if pcs command does not exist
|
||||
def pcs_cli_version()
|
||||
begin
|
||||
pcs_cli_version = `#{PCS_BIN} --version`
|
||||
rescue Errno::ENOENT
|
||||
pcs_cli_version = ''
|
||||
end
|
||||
return pcs_cli_version
|
||||
end
|
||||
|
||||
|
||||
# Ruby 2.5 has dropped Dir::Tmpname.make_tmpname
|
||||
# https://github.com/ruby/ruby/commit/25d56ea7b7b52dc81af30c92a9a0e2d2dab6ff27
|
||||
def pcmk_tmpname((prefix, suffix), n)
|
||||
|
|
|
@ -114,6 +114,16 @@ class pacemaker::corosync(
|
|||
$pcsd_debug = false,
|
||||
) inherits pacemaker {
|
||||
include ::pacemaker::params
|
||||
if ! $cluster_members_rrp {
|
||||
if $::pacemaker::pcs_010 {
|
||||
$cluster_members_rrp_real = pcmk_cluster_setup($cluster_members, $cluster_members_addr, '0.10')
|
||||
} else {
|
||||
$cluster_members_rrp_real = pcmk_cluster_setup($cluster_members, $cluster_members_addr, '0.9')
|
||||
}
|
||||
} else {
|
||||
$cluster_members_rrp_real = $cluster_members_rrp
|
||||
}
|
||||
$cluster_setup_extras_real = inline_template('<%= @cluster_setup_extras.flatten.join(" ") %>')
|
||||
|
||||
if $manage_fw {
|
||||
firewall { '001 corosync mcast':
|
||||
|
@ -162,8 +172,22 @@ class pacemaker::corosync(
|
|||
notify => Exec['reauthenticate-across-all-nodes'],
|
||||
}
|
||||
|
||||
# pcs-0.10.x has different commands to set up the cluster
|
||||
if $::pacemaker::pcs_010 {
|
||||
$cluster_setup_cmd = "${::pacemaker::pcs_bin} cluster setup ${cluster_name} ${cluster_members_rrp_real}"
|
||||
$cluster_reauthenticate_cmd = "${::pacemaker::pcs_bin} host auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd}"
|
||||
$cluster_authenticate_cmd = "${::pacemaker::pcs_bin} host auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd}"
|
||||
$cluster_authenticate_unless = "${::pacemaker::pcs_bin} host auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd} | grep 'Already authorized'"
|
||||
} else {
|
||||
$cluster_setup_cmd = "${::pacemaker::pcs_bin} cluster setup --wait --name ${cluster_name} ${cluster_members_rrp_real} ${cluster_setup_extras_real}"
|
||||
$cluster_reauthenticate_cmd = "${::pacemaker::pcs_bin} cluster auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd} --force"
|
||||
$cluster_authenticate_cmd = "${::pacemaker::pcs_bin} cluster auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd}"
|
||||
$cluster_authenticate_unless = "${::pacemaker::pcs_bin} cluster auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd} | grep 'Already authorized'"
|
||||
}
|
||||
|
||||
|
||||
exec { 'reauthenticate-across-all-nodes':
|
||||
command => "${::pacemaker::pcs_bin} cluster auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd} --force",
|
||||
command => $cluster_reauthenticate_cmd,
|
||||
refreshonly => true,
|
||||
timeout => $settle_timeout,
|
||||
tries => $settle_tries,
|
||||
|
@ -173,13 +197,13 @@ class pacemaker::corosync(
|
|||
}
|
||||
|
||||
exec { 'auth-successful-across-all-nodes':
|
||||
command => "${::pacemaker::pcs_bin} cluster auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd}",
|
||||
command => $cluster_authenticate_cmd,
|
||||
refreshonly => true,
|
||||
timeout => $settle_timeout,
|
||||
tries => $settle_tries,
|
||||
try_sleep => $settle_try_sleep,
|
||||
require => [Service['pcsd'], User['hacluster']],
|
||||
unless => "${::pacemaker::pcs_bin} cluster auth ${cluster_members} -u hacluster -p ${::pacemaker::hacluster_pwd} | grep 'Already authorized'",
|
||||
unless => $cluster_authenticate_unless,
|
||||
tag => 'pacemaker-auth',
|
||||
}
|
||||
|
||||
|
@ -216,18 +240,11 @@ class pacemaker::corosync(
|
|||
Exec <|tag == 'pacemaker-auth'|> -> Exec <|tag == 'pacemaker-scaleup'|>
|
||||
}
|
||||
|
||||
if ! $cluster_members_rrp {
|
||||
$cluster_members_rrp_real = pcmk_cluster_setup($cluster_members, $cluster_members_addr)
|
||||
} else {
|
||||
$cluster_members_rrp_real = $cluster_members_rrp
|
||||
}
|
||||
|
||||
$cluster_setup_extras_real = inline_template('<%= @cluster_setup_extras.flatten.join(" ") %>')
|
||||
Exec <|tag == 'pacemaker-auth'|>
|
||||
->
|
||||
exec {"Create Cluster ${cluster_name}":
|
||||
creates => '/etc/cluster/cluster.conf',
|
||||
command => "${::pacemaker::pcs_bin} cluster setup --wait --name ${cluster_name} ${cluster_members_rrp_real} ${cluster_setup_extras_real}",
|
||||
command => $cluster_setup_cmd,
|
||||
timeout => $cluster_start_timeout,
|
||||
tries => $cluster_start_tries,
|
||||
try_sleep => $cluster_start_try_sleep,
|
||||
|
|
|
@ -50,6 +50,12 @@ class pacemaker::params {
|
|||
} else {
|
||||
$pcmk_remote_package_list = ['pacemaker','pcs','fence-agents-all','pacemaker-libs', 'pacemaker-remote']
|
||||
}
|
||||
# Detect pcs 0.10.x versions and use different commands
|
||||
if $::operatingsystemrelease =~ /8\..*$/ {
|
||||
$pcs_010 = true
|
||||
} else {
|
||||
$pcs_010 = false
|
||||
}
|
||||
$service_name = 'pacemaker'
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -2,24 +2,40 @@ 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/) }
|
||||
it { is_expected.to run.with_params('n1', [], []).and_raise_error(Puppet::Error, /pcmk_cluster_setup: Got unsupported version input data/) }
|
||||
it { is_expected.to run.with_params(123,[], '0.9').and_raise_error(Puppet::Error, /pcmk_cluster_setup: Got unsupported nodes input data/) }
|
||||
it { is_expected.to run.with_params('foo', 'bar', '0.9').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'], '0.9').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(123,[], '0.10').and_raise_error(Puppet::Error, /pcmk_cluster_setup: Got unsupported nodes input data/) }
|
||||
it { is_expected.to run.with_params('foo', 'bar', '0.10').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'], '0.10').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], '0.10').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')
|
||||
it 'returns the original node string when no addresses are specified with pcs 0.10' do
|
||||
is_expected.to run.with_params('n1 n2 n3', [], '0.10').and_return('n1 n2 n3')
|
||||
is_expected.to run.with_params('n1 n2', [], '0.10').and_return('n1 n2')
|
||||
is_expected.to run.with_params('n1', [], '0.10').and_return('n1')
|
||||
is_expected.to run.with_params('n1 ', [], '0.10').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')
|
||||
it 'returns the original node string when no addresses are specified with pcs 0.9' do
|
||||
is_expected.to run.with_params('n1 n2 n3', [], '0.9').and_return('n1 n2 n3')
|
||||
is_expected.to run.with_params('n1 n2', [], '0.9').and_return('n1 n2')
|
||||
is_expected.to run.with_params('n1', [], '0.9').and_return('n1')
|
||||
is_expected.to run.with_params('n1 ', [], '0.9').and_return('n1')
|
||||
end
|
||||
|
||||
it 'returns the correct cluster setup cmd given both nodes and ip address with pcs 0.10' 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'], '0.10').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']], '0.10').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']], '0.10').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'], '0.10').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'], '0.10').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
|
||||
|
||||
it 'returns the correct cluster setup cmd given both nodes and ip address with pcs 0.9' 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'], '0.9').and_return('ctr-0 ctr-1 ctr-2')
|
||||
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'], '0.9').and_return('ctr-0 ctr-1 ctr-2')
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue