
Done for consistency with #reconfigure_command and #delete_command, and also bearing in mind that in future it's conceivable that the configuration command might not always use crm, or might use other commands in conjunction with crm (c.f. #reconfigure_command).
166 lines
4.2 KiB
Ruby
166 lines
4.2 KiB
Ruby
require 'mixlib/shellout'
|
|
|
|
module Pacemaker
|
|
class CIBObject
|
|
attr_accessor :name, :definition
|
|
|
|
@@subclasses = { } unless class_variable_defined?(:@@subclasses)
|
|
|
|
class << self
|
|
attr_reader :object_type
|
|
|
|
def register_type(type_name)
|
|
@object_type = type_name
|
|
@@subclasses[type_name] = self
|
|
end
|
|
|
|
def get_definition(name)
|
|
cmd = Mixlib::ShellOut.new("crm configure show #{name}")
|
|
cmd.environment['HOME'] = ENV.fetch('HOME', '/root')
|
|
cmd.run_command
|
|
begin
|
|
cmd.error!
|
|
cmd.stdout
|
|
rescue
|
|
nil
|
|
end
|
|
end
|
|
|
|
def definition_type(definition)
|
|
unless definition =~ /\A(\w+)\s/
|
|
raise "Couldn't extract CIB object type from '#{definition}'"
|
|
end
|
|
return $1
|
|
end
|
|
|
|
def from_name(name)
|
|
definition = get_definition(name)
|
|
return nil unless definition and ! definition.empty?
|
|
from_definition(definition)
|
|
end
|
|
|
|
# Make sure this works on Ruby 1.8.7 which is missing
|
|
# Object#singleton_class.
|
|
def singleton_class
|
|
class << self; self; end
|
|
end
|
|
|
|
def from_definition(definition)
|
|
calling_class = self.singleton_class
|
|
this_class = method(__method__).owner
|
|
if calling_class == this_class
|
|
# Invoked via (this) base class
|
|
obj_type = definition_type(definition)
|
|
subclass = @@subclasses[obj_type]
|
|
unless subclass
|
|
raise "No subclass of #{self.name} was registered with type '#{obj_type}'"
|
|
end
|
|
return subclass.from_definition(definition)
|
|
else
|
|
# Invoked via subclass
|
|
obj = new(name)
|
|
unless name == obj.name
|
|
raise "Name '#{obj.name}' in definition didn't match name '#{name}' used for retrieval"
|
|
end
|
|
obj.definition = definition
|
|
obj.parse_definition
|
|
obj
|
|
end
|
|
end
|
|
|
|
def from_chef_resource(resource)
|
|
new(resource.name).copy_attrs_from_chef_resource(resource,
|
|
*attrs_to_copy_from_chef)
|
|
end
|
|
|
|
def attrs_to_copy_from_chef
|
|
raise NotImplementedError, "#{self.class} didn't implement attrs_to_copy_from_chef"
|
|
end
|
|
end
|
|
|
|
def initialize(name)
|
|
@name = name
|
|
@definition = nil
|
|
end
|
|
|
|
def copy_attrs_from_chef_resource(resource, *attrs)
|
|
attrs.each do |attr|
|
|
value = resource.send(attr.to_sym)
|
|
writer = (attr + '=').to_sym
|
|
send(writer, value)
|
|
end
|
|
self
|
|
end
|
|
|
|
def copy_attrs_to_chef_resource(resource, *attrs)
|
|
attrs.each do |attr|
|
|
value = send(attr.to_sym)
|
|
writer = attr.to_sym
|
|
resource.send(writer, value)
|
|
end
|
|
end
|
|
|
|
def load_definition
|
|
@definition = self.class.get_definition(name)
|
|
|
|
if @definition and ! @definition.empty? and type != self.class.object_type
|
|
raise CIBObject::TypeMismatch, \
|
|
"Expected #{self.class.object_type} type but loaded definition was type #{type}"
|
|
end
|
|
end
|
|
|
|
def parse_definition
|
|
raise NotImplementedError, "#{self.class} must implement #parse_definition"
|
|
end
|
|
|
|
def exists?
|
|
!! (definition && ! definition.empty?)
|
|
end
|
|
|
|
def type
|
|
self.class.definition_type(definition)
|
|
end
|
|
|
|
def to_s
|
|
"%s '%s'" % [self.class.description, name]
|
|
end
|
|
|
|
def definition_indent
|
|
' ' * 9
|
|
end
|
|
|
|
def continuation_line(text)
|
|
" \\\n#{definition_indent}#{text}"
|
|
end
|
|
|
|
# Returns a single-quoted shell-escaped version of the definition
|
|
# string, suitable for use in a command like:
|
|
#
|
|
# echo '...' | crm configure load update -
|
|
def quoted_definition_string
|
|
"'%s'" % \
|
|
definition_string \
|
|
.gsub('\\') { '\\\\' } \
|
|
.gsub("'") { "\\'" }
|
|
end
|
|
|
|
def configure_command
|
|
"crm configure " + definition_string
|
|
end
|
|
|
|
def reconfigure_command
|
|
"echo #{quoted_definition_string} | crm configure load update -"
|
|
end
|
|
|
|
def delete_command
|
|
"crm configure delete '#{name}'"
|
|
end
|
|
end
|
|
|
|
class CIBObject::DefinitionParseError < StandardError
|
|
end
|
|
|
|
class CIBObject::TypeMismatch < StandardError
|
|
end
|
|
end
|