
The previous use of require caused File.join on several occasions to calculate different paths to the same library, depending on which __FILE__ the library was being calculated as relative to; e.g. /some/path/prefix/spec/one/bar.rb would do the equivalent of: require '/some/path/prefix/spec/one/../../libraries/foo/mylib.rb' and /some/path/prefix/spec/two/baz.rb would do the equivalent of: require '/some/path/prefix/spec/two/../../libraries/foo/mylib.rb' This would result in mylib.rb being loaded multiple times, causing warnings from constants being redefined, and worse, multiple objects representing the same class hierarchy (@@foo) variables. The latter actually broke the @@subclasses registration mechanism in Pacemaker::CIBObject. By switching to File.expand_path, we ensure we always refer to each library using a single absolute path, which means Ruby's require mechanism works as it should, only loading the code the first time round.
126 lines
3.1 KiB
Ruby
126 lines
3.1 KiB
Ruby
require 'shellwords'
|
|
require File.expand_path('../resource', File.dirname(__FILE__))
|
|
|
|
class Pacemaker::Resource::Primitive < Pacemaker::Resource
|
|
TYPE = 'primitive'
|
|
|
|
register_type TYPE
|
|
|
|
attr_accessor :agent, :params, :meta, :op
|
|
|
|
def initialize(*args)
|
|
super(*args)
|
|
|
|
@agent = nil
|
|
end
|
|
|
|
def self.from_chef_resource(resource)
|
|
new(resource.name).copy_attrs_from_chef_resource(resource, *%w(agent params meta op))
|
|
end
|
|
|
|
def parse_definition
|
|
unless definition =~ /\Aprimitive (\S+) (\S+)/
|
|
raise Pacemaker::CIBObject::DefinitionParseError, \
|
|
"Couldn't parse definition '#{definition}'"
|
|
end
|
|
self.name = $1
|
|
self.agent = $2
|
|
|
|
%w(params meta).each do |data_type|
|
|
hash = self.class.extract_hash(definition, data_type)
|
|
writer = (data_type + '=').to_sym
|
|
send(writer, hash)
|
|
end
|
|
|
|
self.op = {}
|
|
%w(start stop monitor).each do |op|
|
|
h = self.class.extract_hash(definition, "op #{op}")
|
|
self.op[op] = h unless h.empty?
|
|
end
|
|
end
|
|
|
|
def params_string
|
|
self.class.params_string(params)
|
|
end
|
|
|
|
def meta_string
|
|
self.class.meta_string(meta)
|
|
end
|
|
|
|
def op_string
|
|
self.class.op_string(op)
|
|
end
|
|
|
|
def definition_string
|
|
str = "#{TYPE} #{name} #{agent}"
|
|
indent = ' ' * 9
|
|
%w(params meta op).each do |data_type|
|
|
unless send(data_type).empty?
|
|
data_string = send("#{data_type}_string")
|
|
str << " \\\n#{indent}#{data_string}"
|
|
else
|
|
end
|
|
end
|
|
str
|
|
end
|
|
|
|
def crm_configure_command
|
|
args = %w(crm configure primitive)
|
|
args << [name, agent, params_string, meta_string, op_string]
|
|
args.join " "
|
|
end
|
|
|
|
def self.params_string(params)
|
|
return "" if ! params or params.empty?
|
|
"params " +
|
|
params.sort.map do |key, value|
|
|
%'#{key}="#{value}"'
|
|
end.join(' ')
|
|
end
|
|
|
|
def self.meta_string(meta)
|
|
return "" if ! meta or meta.empty?
|
|
"meta " +
|
|
meta.sort.map do |key, value|
|
|
%'#{key}="#{value}"'
|
|
end.join(' ')
|
|
end
|
|
|
|
def self.op_string(ops)
|
|
return "" if ! ops or ops.empty?
|
|
ops.sort.map do |op, attrs|
|
|
attrs.empty? ? nil : "op #{op} " + \
|
|
attrs.sort.map do |key, value|
|
|
%'#{key}="#{value}"'
|
|
end.join(' ')
|
|
end.compact.join(' ')
|
|
end
|
|
|
|
# CIB object definitions look something like:
|
|
#
|
|
# primitive keystone ocf:openstack:keystone \
|
|
# params os_username="crowbar" os_password="crowbar" os_tenant_name="openstack" \
|
|
# meta target-role="Started" is-managed="true" \
|
|
# op monitor interval="10" timeout=30s \
|
|
# op start interval="10s" timeout="240" \
|
|
#
|
|
# This method extracts a Hash from one of the params / meta / op lines.
|
|
def self.extract_hash(obj_definition, data_type)
|
|
unless obj_definition =~ /\s+#{data_type} (.+?)\s*\\?$/
|
|
return {}
|
|
end
|
|
|
|
h = {}
|
|
Shellwords.split($1).each do |kvpair|
|
|
break if kvpair == 'op'
|
|
unless kvpair =~ /^(.+?)=(.+)$/
|
|
raise "Couldn't understand '#{kvpair}' for '#{data_type}' section "\
|
|
"of #{name} primitive (definition was [#{obj_definition}])"
|
|
end
|
|
h[$1] = $2.sub(/^"(.*)"$/, "\1")
|
|
end
|
|
h
|
|
end
|
|
|
|
end
|