puppet-pacemaker/lib/pacemaker/type.rb

185 lines
6.7 KiB
Ruby

module Pacemaker
# contains functions that can be included to the pacemaker types
module Type
# output IS and SHOULD values for debugging
# @param is [Object] the current value of the parameter
# @param should [Object] the catalog value of the parameter
# @param tag [String] log tag comment to trace calls
def insync_debug(is, should, tag = nil)
debug "insync?: #{tag}" if tag
debug "IS: #{is.inspect} #{is.class}"
debug "SH: #{should.inspect} #{should.class}"
end
# return inspected data structure, used in should_to_s and is_to_s functions
# @param data [Object]
# @return [String]
def inspect_to_s(data)
data.inspect
end
# convert data structure's keys and values to strings
# @param data [Object]
# @return [Object]
def stringify_data(data)
if data.is_a? Hash
new_data = {}
data.each do |key, value|
new_data.store stringify_data(key), stringify_data(value)
end
data.clear
data.merge! new_data
elsif data.is_a? Array
data.map! do |element|
stringify_data element
end
elsif data.is_a? Set
raise "unexpected Set data: #{data}"
else
data.to_s
end
end
# Maintains an array of operation hashes as if it was a sorted set. These
# are in Array-of-Hash format ({ 'name' => 'monitor', 'interval' => ...}),
# not { 'monitor' => {...} } ones. The unicity is done on the name and
# interval operation keys. The input is expected to have been stringified
# and munged.
#
# Modifies the operations argument and returns it.
#
# We can't use a real Set as it doesn't serialize correctly in Puppet's
# transaction store. This datastructure is always small, so performance
# is irrelevant.
def add_to_operations_array(operations, new_op)
operations.delete_if { |op| op['name'] == new_op['name'] && op['interval'] == new_op['interval'] }
operations << new_op
operations.sort_by! { |op| "#{op['name']} #{op['interval']}" }
end
# Munges the input into an Array of munged operations.
# @param [Hash,Array] operations_input parameter value from catalog
def munge_operations_array(operations_input)
operations_input = stringify_data(operations_input)
operations_input = [operations_input] unless operations_input.is_a? Array
operations = []
operations_input.each do |operation|
# operations were provided as an array of hashes
if operation.is_a? Hash and operation['name']
munge_operation operation
add_to_operations_array(operations, operation)
elsif operation.is_a? Hash
# operations were provided as a hash of hashes
operation.each do |operation_name, operation_data|
raise "invalid operation in a hash of hashes: #{operation_data}" unless operation_data.is_a? Hash
operation = {}
if operation_name.include? ':'
operation_name_array = operation_name.split(':')
operation_name = operation_name_array[0]
if not operation_data['role'] and operation_name_array[1]
operation_data['role'] = operation_name_array[1]
end
end
operation['name'] = operation_name
operation.merge! operation_data
munge_operation operation
add_to_operations_array(operations, operation) if operation.any?
end
else
raise "invalid pacemaker_resource.operations input: #{operations_input}"
end
end
operations
end
# munge a single operations hash
# @param [Hash] operation
def munge_operation(operation)
raise "invalid pacemaker_resource.operations element: #{operation}" unless operation.is_a? Hash
operation['name'] = 'monitor' unless operation['name']
operation['interval'] = '0' unless operation['name'] == 'monitor'
operation['interval'] = '0' unless operation['interval']
operation['role'].capitalize! if operation['role']
operation
end
# compare meta_attribute hashes excluding status meta attributes
# @param is [Hash]
# @param should [Hash]
# @return [TrueClass,FalseClass]
def compare_meta_attributes(is, should)
return unless is.is_a?(Hash) && should.is_a?(Hash)
is_without_state = is.reject do |k, _v|
pacemaker_options[:status_meta_attributes].include? k.to_s
end
should_without_state = should.reject do |k, _v|
pacemaker_options[:status_meta_attributes].include? k.to_s
end
result = is_without_state == should_without_state
debug "compare_meta_attributes: #{result}"
result
end
# sort operations array before insync?
# to make different order and same data arrays equal
# @param is [Array]
# @param should [Array]
# @return [TrueClass,FalseClass]
def compare_operations(is, should)
is = is.first if is.is_a? Array
should = should.first if should.is_a? Array
result = (is == should)
debug "compare_operations: #{result}"
result
end
# remove status related meta attributes
# from the meta attributes hash
# @param attributes_from [Hash]
# @return [Hash]
def munge_meta_attributes(attributes_from)
attributes_to = {}
attributes_from.each do |name, parameters|
next if pacemaker_options[:status_meta_attributes].include? name
attributes_to.store name, parameters
end
attributes_to
end
# normalize a single location rule
# @param rule [Hash] rule structure
# @param rule_number [Integer] rule index number
# @param title [String] constraint name
# @return [Hash] normalized rule structure
def munge_rule(rule, rule_number, title)
rule['id'] = "#{title}-rule-#{rule_number}" unless rule['id']
rule['boolean-op'] = 'or' unless rule['boolean-op']
rule['score'].gsub! 'inf', 'INFINITY' if rule['score']
if rule['expressions']
unless rule['expressions'].is_a? Array
expressions_array = []
expressions_array << rule['expressions']
rule['expressions'] = expressions_array
end
expression_number = 0
rule['expressions'].each do |expression|
unless expression['id']
expression['id'] = "#{title}-rule-#{rule_number}-expression-#{expression_number}"
end
expression_number += 1
end
end
rule
end
# remove "-clone" or "-master" suffix
# and "role" suffix (:Master, :Slave) from a primitive's name
# @param primitive [String]
# @return [String]
def primitive_base_name(primitive)
primitive = primitive.split(':').first
primitive.gsub(/-clone$|-master$/, '')
end
end
end