Add new pcs 0.10 compatible remote addition implementation
New pcs 0.10 needs to implement remotes addition in a completely different way. It is not sufficient anymore to just create the ocf::pacemaker::remote resource and make sure that pacemaker_remote is up and running with the same authkey on all nodes. Now we need to setup pcsd on all nodes (remotes and controllers), setup the hacluster user and then do a pcs cluster remote-add command. We do this only when pcs 0.10 is detected in order to maintain the old proven behaviour on pcs 0.9x. Tested this on stein + rhel8 correctly get remotes working on an IHA setup: [root@controller-0 galera-bundle-1]# pcs status Cluster name: tripleo_cluster Stack: corosync Current DC: controller-1 (version 2.0.1-4.el8-0eb7991564) - partition with quorum Last updated: Thu May 23 05:52:33 2019 Last change: Tue May 21 14:20:14 2019 by root via cibadmin on controller-0 17 nodes configured 72 resources configured Online: [ controller-0 controller-1 controller-2 ] RemoteOnline: [ compute-0 compute-1 ] Full list of resources: compute-0 (ocf::pacemaker:remote): Started controller-0 compute-1 (ocf::pacemaker:remote): Started controller-1 Also tested on queens to make sure no regressions in the old codepaths are introduced. Additionally tested a redeploy on stein to make sure idempotency is preserved. Change-Id: I852d5d7aa8578c45f0c7215827cedd4ea72c8d0b
This commit is contained in:
parent
0c5d69921d
commit
fde568564d
|
@ -0,0 +1,130 @@
|
|||
require_relative '../pcmk_common'
|
||||
|
||||
Puppet::Type.type(:pcmk_remote).provide(:default) do
|
||||
desc 'A remote resource definition for pacemaker resource'
|
||||
|
||||
def build_pcs_auth_cmd()
|
||||
if @resource[:pcs_user] == '' or @resource[:pcs_password] == ''
|
||||
raise(Puppet::Error, "When using the new pcs cluster node backend for remotes " +
|
||||
"'pcs_user' and 'pcs_password must be both defined (#{@resource[:pcs_user]} " +
|
||||
"#{@resource[:pcs_password]})")
|
||||
end
|
||||
# Build the 'pcs resource create' command. Check out the pcs man page :-)
|
||||
cmd = 'host auth ' + @resource[:name]
|
||||
if not_empty_string(@resource[:remote_address])
|
||||
cmd += ' addr=' + @resource[:remote_address]
|
||||
end
|
||||
cmd += ' -u ' + @resource[:pcs_user] + ' -p "' + @resource[:pcs_password] + '"'
|
||||
cmd
|
||||
end
|
||||
|
||||
def build_pcs_remote_cmd()
|
||||
resource_params = @resource[:resource_params]
|
||||
meta_params = @resource[:meta_params]
|
||||
op_params = @resource[:op_params]
|
||||
|
||||
# Build the 'pcs resource create' command. Check out the pcs man page :-)
|
||||
cmd = 'cluster node add-remote ' + @resource[:name]
|
||||
if not_empty_string(@resource[:remote_address])
|
||||
cmd += ' ' + @resource[:remote_address]
|
||||
end
|
||||
if not_empty_string(resource_params)
|
||||
cmd += ' ' + resource_params
|
||||
end
|
||||
if not_empty_string(meta_params)
|
||||
cmd += ' meta ' + meta_params
|
||||
end
|
||||
if not_empty_string(op_params)
|
||||
cmd += ' op ' + op_params
|
||||
end
|
||||
cmd
|
||||
end
|
||||
|
||||
### overloaded methods
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
Puppet.debug("puppet-pacemaker: initialize()")
|
||||
# Hash to store the existance state of each resource
|
||||
@resources_state = {}
|
||||
end
|
||||
|
||||
def create
|
||||
did_resource_exist = @resources_state[@resource[:name]] == PCMK_NOCHANGENEEDED
|
||||
|
||||
cmd_auth = build_pcs_auth_cmd()
|
||||
cmd_remote = build_pcs_remote_cmd()
|
||||
|
||||
pcs_without_push('create', @resource[:name], cmd_auth, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:post_success_sleep])
|
||||
pcs_without_push('create', @resource[:name], cmd_remote, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:post_success_sleep])
|
||||
end
|
||||
|
||||
def destroy
|
||||
cmd = 'cluster node delete-remote ' + @resource[:name]
|
||||
pcs_without_push('delete', @resource[:name], cmd, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:post_success_sleep])
|
||||
end
|
||||
|
||||
def exists?
|
||||
@resources_state[@resource[:name]] = resource_exists?
|
||||
did_resource_exist = @resources_state[@resource[:name]] == PCMK_NOCHANGENEEDED
|
||||
Puppet.debug("Exists: resource #{@resource[:name]} exists "\
|
||||
"#{@resources_state[@resource[:name]]} "\
|
||||
"resource deep_compare: #{@resource[:deep_compare]}")
|
||||
if did_resource_exist
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def resource_exists?
|
||||
cmd = 'resource show ' + @resource[:name] + ' > /dev/null 2>&1'
|
||||
ret = pcs('show', @resource[:name], cmd, @resource[:tries],
|
||||
@resource[:try_sleep], false, @resource[:post_success_sleep])
|
||||
if ret == false then
|
||||
return PCMK_NOTEXISTS
|
||||
end
|
||||
return PCMK_NOCHANGENEEDED
|
||||
end
|
||||
|
||||
### property methods
|
||||
|
||||
# It isn't an easy road if you want to make these true
|
||||
# puppet-like resource properties. Here is a start if you are feeling brave:
|
||||
# https://github.com/cwolferh/puppet-pacemaker/blob/pcmk_resource_improvements_try0/lib/puppet/provider/pcmk_resource/default.rb#L64
|
||||
def resource_params
|
||||
@resource[:resource_params]
|
||||
end
|
||||
|
||||
def resource_params=(value)
|
||||
end
|
||||
|
||||
def op_params
|
||||
@resource[:op_params]
|
||||
end
|
||||
|
||||
def op_params=(value)
|
||||
end
|
||||
|
||||
def meta_params
|
||||
@resource[:meta_params]
|
||||
end
|
||||
|
||||
def meta_params=(value)
|
||||
end
|
||||
|
||||
def reconnect_interval
|
||||
@resource[:reconnect_interval]
|
||||
end
|
||||
|
||||
def reconnect_interval=(value)
|
||||
end
|
||||
|
||||
def remote_address
|
||||
@resource[:remote_address]
|
||||
end
|
||||
|
||||
def remote_address=(value)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,131 @@
|
|||
require 'puppet/parameter/boolean'
|
||||
|
||||
Puppet::Type.newtype(:pcmk_remote) do
|
||||
@doc = "Remote resource definition for a pacemaker"
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name) do
|
||||
desc "A unique name for the resource"
|
||||
end
|
||||
|
||||
newparam(:pcs_user) do
|
||||
desc "Pcs user to use when authenticating a remote node"
|
||||
defaultto ''
|
||||
end
|
||||
|
||||
newparam(:pcs_password) do
|
||||
desc "Pcs password to use when authenticating a remote node"
|
||||
defaultto ''
|
||||
end
|
||||
|
||||
newparam(:post_success_sleep) do
|
||||
desc "The time to sleep after successful pcs action. The reason to set
|
||||
this is to avoid immediate back-to-back 'pcs resource create' calls
|
||||
when creating multiple resources. Defaults to '0'."
|
||||
|
||||
munge do |value|
|
||||
if value.is_a?(String)
|
||||
unless value =~ /^[-\d.]+$/
|
||||
raise ArgumentError, "post_success_sleep must be a number"
|
||||
end
|
||||
value = Float(value)
|
||||
end
|
||||
raise ArgumentError, "post_success_sleep cannot be a negative number" if value < 0
|
||||
value
|
||||
end
|
||||
|
||||
defaultto 0
|
||||
end
|
||||
|
||||
## borrowed from exec.rb
|
||||
newparam(:tries) do
|
||||
desc "The number of times to attempt to create a pcs resource.
|
||||
Defaults to '1'."
|
||||
|
||||
munge do |value|
|
||||
if value.is_a?(String)
|
||||
unless value =~ /^[\d]+$/
|
||||
raise ArgumentError, "Tries must be an integer"
|
||||
end
|
||||
value = Integer(value)
|
||||
end
|
||||
raise ArgumentError, "Tries must be an integer >= 1" if value < 1
|
||||
value
|
||||
end
|
||||
|
||||
defaultto 1
|
||||
end
|
||||
|
||||
newparam(:try_sleep) do
|
||||
desc "The time to sleep in seconds between 'tries'."
|
||||
|
||||
munge do |value|
|
||||
if value.is_a?(String)
|
||||
unless value =~ /^[-\d.]+$/
|
||||
raise ArgumentError, "try_sleep must be a number"
|
||||
end
|
||||
value = Float(value)
|
||||
end
|
||||
raise ArgumentError, "try_sleep cannot be a negative number" if value < 0
|
||||
value
|
||||
end
|
||||
|
||||
defaultto 0
|
||||
end
|
||||
|
||||
newproperty(:op_params) do
|
||||
desc "op parameters"
|
||||
end
|
||||
newproperty(:meta_params) do
|
||||
desc "meta parameters"
|
||||
end
|
||||
newproperty(:resource_params) do
|
||||
desc "resource parameters"
|
||||
end
|
||||
newproperty(:remote_address) do
|
||||
desc "Address for remote resources"
|
||||
end
|
||||
newproperty(:reconnect_interval) do
|
||||
desc "reconnection interval for remote resources"
|
||||
munge do |value|
|
||||
if value.is_a?(String)
|
||||
unless value =~ /^[-\d.]+$/
|
||||
raise ArgumentError, "reconnect_interval must be a number"
|
||||
end
|
||||
value = Float(value)
|
||||
end
|
||||
raise ArgumentError, "reconnect_interval cannot be a negative number" if value < 0
|
||||
value
|
||||
end
|
||||
|
||||
defaultto 60
|
||||
end
|
||||
|
||||
newparam(:deep_compare, :boolean => true, :parent => Puppet::Parameter::Boolean) do
|
||||
desc "Whether to enable deep comparing of resource
|
||||
When set to true a resource will be compared in full (options, meta parameters,..)
|
||||
to the existing one and in case of difference it will be repushed to the CIB
|
||||
Defaults to `false`."
|
||||
|
||||
defaultto false
|
||||
end
|
||||
|
||||
newparam(:update_settle_secs) do
|
||||
desc "The time in seconds to wait for the cluster to settle after resource has been updated
|
||||
when :deep_compare kicked in. Defaults to '600'."
|
||||
|
||||
munge do |value|
|
||||
if value.is_a?(String)
|
||||
unless value =~ /^[-\d.]+$/
|
||||
raise ArgumentError, "update_settle_secs must be a number"
|
||||
end
|
||||
value = Float(value)
|
||||
end
|
||||
raise ArgumentError, "update_settle_secs cannot be a negative number" if value < 0
|
||||
value
|
||||
end
|
||||
|
||||
defaultto 600
|
||||
end
|
||||
end
|
|
@ -271,7 +271,8 @@ class pacemaker::corosync(
|
|||
Exec['wait-for-settle']
|
||||
}
|
||||
|
||||
if $remote_authkey {
|
||||
# pcs 0.10/pcmk 2.0 take care of the authkey internally by themselves
|
||||
if $remote_authkey and !$::pacemaker::pcs_010 {
|
||||
file { 'etc-pacemaker':
|
||||
ensure => directory,
|
||||
path => '/etc/pacemaker',
|
||||
|
|
|
@ -20,33 +20,95 @@
|
|||
#
|
||||
# === Parameters
|
||||
#
|
||||
# [*use_pcsd*]
|
||||
# (optional) Should the remote use pcsd to be setup
|
||||
# Defaults to false
|
||||
#
|
||||
# [*manage_fw*]
|
||||
# (optional) Manage or not IPtables rules.
|
||||
# Defaults to true
|
||||
#
|
||||
# [*remote_authkey*]
|
||||
# (Required) Authkey for pacemaker remote nodes
|
||||
# Defaults to undef
|
||||
#
|
||||
class pacemaker::remote ($remote_authkey) {
|
||||
# [*pcsd_debug*]
|
||||
# (optional) Enable pcsd debugging
|
||||
# Defaults to false
|
||||
#
|
||||
class pacemaker::remote (
|
||||
$remote_authkey,
|
||||
$use_pcsd = false,
|
||||
$pcs_user = 'hacluster',
|
||||
$pcs_password = undef,
|
||||
$manage_fw = true,
|
||||
$pcsd_debug = false,
|
||||
) {
|
||||
include ::pacemaker::params
|
||||
ensure_resource('package', $::pacemaker::params::pcmk_remote_package_list, {
|
||||
ensure => present
|
||||
})
|
||||
Package<| title == 'pacemaker-remote' |> -> File <| title == 'etc-pacemaker' |>
|
||||
|
||||
file { 'etc-pacemaker':
|
||||
ensure => directory,
|
||||
path => '/etc/pacemaker',
|
||||
owner => 'hacluster',
|
||||
group => 'haclient',
|
||||
mode => '0750',
|
||||
} ->
|
||||
file { 'etc-pacemaker-authkey':
|
||||
path => '/etc/pacemaker/authkey',
|
||||
owner => 'hacluster',
|
||||
group => 'haclient',
|
||||
mode => '0640',
|
||||
content => $remote_authkey,
|
||||
} ->
|
||||
service { 'pacemaker_remote':
|
||||
ensure => running,
|
||||
enable => true,
|
||||
# pacemaker remote needs pcsd only with pcs >= 0.10
|
||||
if $use_pcsd {
|
||||
include ::pacemaker::install
|
||||
if $manage_fw {
|
||||
firewall { '001 pcsd':
|
||||
proto => 'tcp',
|
||||
dport => ['2224'],
|
||||
action => 'accept',
|
||||
}
|
||||
firewall { '001 pcsd ipv6':
|
||||
proto => 'tcp',
|
||||
dport => ['2224'],
|
||||
action => 'accept',
|
||||
provider => 'ip6tables',
|
||||
}
|
||||
}
|
||||
$pcsd_debug_str = bool2str($pcsd_debug)
|
||||
file_line { 'pcsd_debug_ini':
|
||||
path => $::pacemaker::params::pcsd_sysconfig,
|
||||
line => "PCSD_DEBUG=${pcsd_debug_str}",
|
||||
match => '^PCSD_DEBUG=',
|
||||
require => Class['::pacemaker::install'],
|
||||
before => Service['pcsd'],
|
||||
notify => Service['pcsd'],
|
||||
}
|
||||
user { $pcs_user:
|
||||
password => pw_hash($pcs_password, 'SHA-512', fqdn_rand_string(10)),
|
||||
groups => 'haclient',
|
||||
require => Class['::pacemaker::install'],
|
||||
before => Service['pcsd'],
|
||||
}
|
||||
# only set up pcsd, not the other cluster services which have
|
||||
# very specific setup and when-to-start-up requirements
|
||||
# that are taken care of in corosync.pp
|
||||
service { 'pcsd':
|
||||
ensure => running,
|
||||
hasstatus => true,
|
||||
hasrestart => true,
|
||||
enable => true,
|
||||
require => Class['::pacemaker::install'],
|
||||
}
|
||||
} else {
|
||||
# This gets managed by pcsd directly when pcs is < 0.10
|
||||
Package<| title == 'pacemaker-remote' |> -> File <| title == 'etc-pacemaker' |>
|
||||
file { 'etc-pacemaker':
|
||||
ensure => directory,
|
||||
path => '/etc/pacemaker',
|
||||
owner => 'hacluster',
|
||||
group => 'haclient',
|
||||
mode => '0750',
|
||||
} ->
|
||||
file { 'etc-pacemaker-authkey':
|
||||
path => '/etc/pacemaker/authkey',
|
||||
owner => 'hacluster',
|
||||
group => 'haclient',
|
||||
mode => '0640',
|
||||
content => $remote_authkey,
|
||||
} ->
|
||||
service { 'pacemaker_remote':
|
||||
ensure => running,
|
||||
enable => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,24 +106,43 @@ define pacemaker::resource::remote(
|
|||
$tries = 1,
|
||||
$try_sleep = 0,
|
||||
$verify_on_create = false,
|
||||
$pcs_user = 'hacluster',
|
||||
$pcs_password = undef,
|
||||
$location_rule = undef,
|
||||
$deep_compare = hiera('pacemaker::resource::remote::deep_compare', false),
|
||||
$update_settle_secs = hiera('pacemaker::resource::remote::update_settle_secs', 600),
|
||||
) {
|
||||
pcmk_resource { $name:
|
||||
ensure => $ensure,
|
||||
resource_type => 'remote',
|
||||
remote_address => $remote_address,
|
||||
reconnect_interval => $reconnect_interval,
|
||||
resource_params => $resource_params,
|
||||
meta_params => $meta_params,
|
||||
op_params => $op_params,
|
||||
bundle => $bundle,
|
||||
tries => $tries,
|
||||
try_sleep => $try_sleep,
|
||||
verify_on_create => $verify_on_create,
|
||||
location_rule => $location_rule,
|
||||
deep_compare => $deep_compare,
|
||||
update_settle_secs => $update_settle_secs,
|
||||
if $::pacemaker::params::pcs_010 {
|
||||
pcmk_remote { $name:
|
||||
ensure => $ensure,
|
||||
remote_address => $remote_address,
|
||||
reconnect_interval => $reconnect_interval,
|
||||
resource_params => $resource_params,
|
||||
meta_params => $meta_params,
|
||||
op_params => $op_params,
|
||||
tries => $tries,
|
||||
try_sleep => $try_sleep,
|
||||
pcs_user => $pcs_user,
|
||||
pcs_password => $pcs_password,
|
||||
deep_compare => $deep_compare,
|
||||
update_settle_secs => $update_settle_secs,
|
||||
}
|
||||
} else {
|
||||
pcmk_resource { $name:
|
||||
ensure => $ensure,
|
||||
resource_type => 'remote',
|
||||
remote_address => $remote_address,
|
||||
reconnect_interval => $reconnect_interval,
|
||||
resource_params => $resource_params,
|
||||
meta_params => $meta_params,
|
||||
op_params => $op_params,
|
||||
bundle => $bundle,
|
||||
tries => $tries,
|
||||
try_sleep => $try_sleep,
|
||||
verify_on_create => $verify_on_create,
|
||||
location_rule => $location_rule,
|
||||
deep_compare => $deep_compare,
|
||||
update_settle_secs => $update_settle_secs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue