Add pcmk_stonith provider
This new pcmk_stonith provider exists in order to create stonith resources and location constraints using the common pcs() function. The reason for this is that this function contains the retry logic needed in case the CIB gets updated from another node. In this provider we also create the location constraint in a race-free way by first creating the stonith resource in disabled mode, then we create the location constraint and finally we enable the stonith resource. This is to avoid races when creating stonith resources from multiple nodes which is the how they are created within TripleO. Change-Id: I424302bbf8d0d5f233e3a7debc082be1c9a170bb Partial-Bug: #1717566
This commit is contained in:
parent
6c50831a77
commit
375ff16503
|
@ -0,0 +1,83 @@
|
|||
require_relative '../pcmk_common'
|
||||
|
||||
Puppet::Type.type(:pcmk_stonith).provide(:default) do
|
||||
desc 'A base resource definition for a pacemaker stonith'
|
||||
|
||||
### overloaded methods
|
||||
def create
|
||||
name = @resource[:name]
|
||||
stonith_type = @resource[:stonith_type]
|
||||
pcmk_host_list = @resource[:pcmk_host_list]
|
||||
pcs_param_string = @resource[:pcs_param_string]
|
||||
|
||||
# We need to probe the existance of both location and resource
|
||||
# because we do not know why we're being created (if for both or
|
||||
# only for one)
|
||||
did_stonith_location_exist = stonith_location_exists?
|
||||
did_stonith_resource_exist = stonith_resource_exists?
|
||||
Puppet.debug("Create: stonith exists #{did_stonith_resource_exist} location exists #{did_stonith_location_exist}")
|
||||
|
||||
cmd = 'stonith create ' + name + ' ' + stonith_type + ' ' \
|
||||
'pcmk_host_list=' + pcmk_host_list + ' ' + @resource[:pcs_param_string]
|
||||
|
||||
# If both the stonith resource and the location do not exist, we create them both
|
||||
# if a location_rule is specified otherwise only the resource
|
||||
if not did_stonith_location_exist and not did_stonith_resource_exist
|
||||
pcs('create', name, "#{cmd} --disabled", @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
stonith_location_rule_create()
|
||||
pcs('create', name, "resource enable #{name}", @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
# If the location_rule already existed, we only create the resource
|
||||
elsif did_stonith_location_exist and not did_stonith_resource_exist
|
||||
pcs('create', name, cmd, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
# The location_rule does not exist and the resource does exist
|
||||
elsif not did_stonith_location_exist and did_stonith_resource_exist
|
||||
stonith_location_rule_create()
|
||||
else
|
||||
raise Puppet::Error, "Invalid create: #{name} stonith resource exists #{did_stonith_resource_exist} "
|
||||
"stonith location exists #{did_stonith_location_exist}"
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
# Any corresponding location rules will be deleted by
|
||||
# pcs automatically, if present
|
||||
cmd = 'resource delete ' + @resource[:name]
|
||||
pcs('delete', @resource[:name], cmd, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
end
|
||||
|
||||
def exists?
|
||||
did_stonith_location_exist = stonith_location_exists?
|
||||
did_stonith_resource_exist = stonith_resource_exists?
|
||||
Puppet.debug("Exists: stonith resource exists #{did_stonith_resource_exist} location exists #{did_stonith_location_exist}")
|
||||
if did_stonith_resource_exist and did_stonith_location_exist
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def stonith_resource_exists?
|
||||
cmd = 'stonith show ' + @resource[:name] + ' > /dev/null 2>&1'
|
||||
ret = pcs('show', @resource[:name], cmd, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
return ret == false ? false : true
|
||||
end
|
||||
|
||||
def stonith_location_exists?
|
||||
constraint_name = "#{@resource[:name]}"
|
||||
cmd = "constraint location | grep #{constraint_name} > /dev/null 2>&1"
|
||||
ret = pcs('show', @resource[:name], cmd, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
return ret == false ? false : true
|
||||
end
|
||||
|
||||
def stonith_location_rule_create()
|
||||
location_cmd = "constraint location #{@resource[:name]} avoids #{@resource[:pcmk_host_list]}"
|
||||
Puppet.debug("stonith_location_rule_create: #{location_cmd}")
|
||||
pcs('create', @resource[:name], location_cmd, @resource[:tries],
|
||||
@resource[:try_sleep], @resource[:verify_on_create], @resource[:post_success_sleep])
|
||||
end
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
require 'puppet/parameter/boolean'
|
||||
|
||||
Puppet::Type.newtype(:pcmk_stonith) do
|
||||
@doc = "Base resource definition for a pacemaker stonith resource"
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name) do
|
||||
desc "A unique name for the stonith resource"
|
||||
end
|
||||
|
||||
newparam(:stonith_type) do
|
||||
desc "the pacemaker stonith type to create"
|
||||
end
|
||||
|
||||
newparam(:pcmk_host_list) do
|
||||
desc "the pcmk_host_list parameter for pcs"
|
||||
end
|
||||
|
||||
newparam(:pcs_param_string) do
|
||||
desc "the pacemaker pcs string to use"
|
||||
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
|
||||
|
||||
newparam(:verify_on_create, :boolean => true, :parent => Puppet::Parameter::Boolean) do
|
||||
desc "Whether to verify pcs resource creation with an additional
|
||||
call to 'pcs resource show' rather than just relying on the exit
|
||||
status of 'pcs resource create'. When true, $try_sleep
|
||||
determines how long to wait to verify and $post_success_sleep is
|
||||
ignored. Defaults to `false`."
|
||||
|
||||
defaultto false
|
||||
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
|
||||
end
|
Loading…
Reference in New Issue