add Pacemaker::Constraint::Colocation
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
require File.join(File.dirname(__FILE__), %w(pacemaker resource primitive))
|
require File.join(File.dirname(__FILE__), %w(pacemaker resource primitive))
|
||||||
require File.join(File.dirname(__FILE__), %w(pacemaker resource clone))
|
require File.join(File.dirname(__FILE__), %w(pacemaker resource clone))
|
||||||
|
require File.join(File.dirname(__FILE__), %w(pacemaker constraint colocation))
|
||||||
|
10
libraries/pacemaker/constraint.rb
Normal file
10
libraries/pacemaker/constraint.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
require File.join(File.dirname(__FILE__), 'cib_object')
|
||||||
|
|
||||||
|
module Pacemaker
|
||||||
|
class Constraint < Pacemaker::CIBObject
|
||||||
|
def self.description
|
||||||
|
type = self.to_s.split('::').last
|
||||||
|
"#{type} constraint"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
33
libraries/pacemaker/constraint/colocation.rb
Normal file
33
libraries/pacemaker/constraint/colocation.rb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
require File::join(File.dirname(__FILE__), %w(.. constraint))
|
||||||
|
|
||||||
|
class Pacemaker::Constraint::Colocation < Pacemaker::Constraint
|
||||||
|
TYPE = 'colocation'
|
||||||
|
register_type TYPE
|
||||||
|
|
||||||
|
attr_accessor :score, :resources
|
||||||
|
|
||||||
|
def self.from_chef_resource(resource)
|
||||||
|
attrs = %w(score resources)
|
||||||
|
new(resource.name).copy_attrs_from_chef_resource(resource, *attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_definition
|
||||||
|
rsc_re = /(\S+?)(?::(Started|Stopped))?/
|
||||||
|
unless definition =~ /^#{TYPE} (\S+) (\d+|[-+]?inf): (.+?)\s*$/
|
||||||
|
raise Pacemaker::CIBObject::DefinitionParseError, \
|
||||||
|
"Couldn't parse definition '#{definition}'"
|
||||||
|
end
|
||||||
|
self.name = $1
|
||||||
|
self.score = $2
|
||||||
|
self.resources = $3.split
|
||||||
|
end
|
||||||
|
|
||||||
|
def definition_string
|
||||||
|
"colocation #{name} #{score}: " + resources.join(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
def crm_configure_command
|
||||||
|
"crm configure " + definition_string
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@@ -17,55 +17,60 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
require ::File.join(::File.dirname(__FILE__),
|
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker))
|
||||||
*%w(.. libraries pacemaker cib_object))
|
require ::File.join(::File.dirname(__FILE__), 'common')
|
||||||
|
|
||||||
|
include Chef::Mixin::PacemakerCommon
|
||||||
|
|
||||||
action :create do
|
action :create do
|
||||||
name = new_resource.name
|
name = new_resource.name
|
||||||
priority = new_resource.priority
|
|
||||||
multiple = new_resource.multiple
|
|
||||||
|
|
||||||
unless resource_exists?(name)
|
if @current_resource_definition.nil?
|
||||||
if multiple
|
create_resource(name)
|
||||||
multiple_rscs = new_resource.multiple_rscs
|
|
||||||
|
|
||||||
cmd = "crm configure colocation #{name} #{priority}:"
|
|
||||||
multiple_rscs.each do |rsc|
|
|
||||||
cmd << " #{rsc}"
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
rsc = new_resource.rsc
|
maybe_modify_resource(name)
|
||||||
with_rsc = new_resource.with_rsc
|
|
||||||
|
|
||||||
cmd = "crm configure colocation #{name} #{priority}: #{rsc} #{with_rsc}"
|
|
||||||
end
|
|
||||||
|
|
||||||
cmd_ = Mixlib::ShellOut.new(cmd)
|
|
||||||
cmd_.environment['HOME'] = ENV.fetch('HOME', '/root')
|
|
||||||
cmd_.run_command
|
|
||||||
begin
|
|
||||||
cmd_.error!
|
|
||||||
if resource_exists?(name)
|
|
||||||
new_resource.updated_by_last_action(true)
|
|
||||||
Chef::Log.info "Successfully configured colocation '#{name}'."
|
|
||||||
else
|
|
||||||
Chef::Log.error "Failed to configure colocation #{name}."
|
|
||||||
end
|
|
||||||
rescue
|
|
||||||
Chef::Log.error "Failed to configure colocation #{name}."
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
action :delete do
|
action :delete do
|
||||||
name = new_resource.name
|
name = new_resource.name
|
||||||
cmd = "crm resource stop #{name}; crm configure delete #{name}"
|
next unless @current_resource
|
||||||
|
rsc = cib_object_class.new(name)
|
||||||
e = execute "delete colocation #{name}" do
|
execute rsc.delete_command do
|
||||||
command cmd
|
action :nothing
|
||||||
only_if { resource_exists?(name) }
|
end.run_action(:run)
|
||||||
end
|
|
||||||
|
|
||||||
new_resource.updated_by_last_action(true)
|
new_resource.updated_by_last_action(true)
|
||||||
Chef::Log.info "Deleted colocation '#{name}'."
|
Chef::Log.info "Deleted #{@current_cib_object}'."
|
||||||
|
end
|
||||||
|
|
||||||
|
def cib_object_class
|
||||||
|
Pacemaker::Constraint::Colocation
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_current_resource
|
||||||
|
name = @new_resource.name
|
||||||
|
@current_resource = Chef::Resource::PacemakerColocation.new(name)
|
||||||
|
attrs = [:score, :resources]
|
||||||
|
@current_cib_object.copy_attrs_to_chef_resource(@current_resource, *attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_resource(name)
|
||||||
|
standard_create_resource
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_modify_resource(name)
|
||||||
|
Chef::Log.info "Checking existing #{@current_cib_object} for modifications"
|
||||||
|
|
||||||
|
desired_colocation = cib_object_class.from_chef_resource(new_resource)
|
||||||
|
if desired_colocation.definition_string != @current_cib_object.definition_string
|
||||||
|
Chef::Log.debug "changed from [#{@current_cib_object.definition_string}] to [#{desired_colocation.definition_string}]"
|
||||||
|
to_echo = desired_colocation.definition_string.chomp
|
||||||
|
to_echo.gsub!('\\') { '\\\\' }
|
||||||
|
to_echo.gsub!("'", "\\'")
|
||||||
|
cmd = "echo '#{to_echo}' | crm configure load update -"
|
||||||
|
execute cmd do
|
||||||
|
action :nothing
|
||||||
|
end.run_action(:run)
|
||||||
|
new_resource.updated_by_last_action(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -22,8 +22,5 @@ actions :create, :delete
|
|||||||
default_action :create
|
default_action :create
|
||||||
|
|
||||||
attribute :name, :kind_of => String, :name_attribute => true
|
attribute :name, :kind_of => String, :name_attribute => true
|
||||||
attribute :priority, :kind_of => String
|
attribute :score, :kind_of => String
|
||||||
attribute :multiple, :default => false
|
attribute :resources, :kind_of => Array
|
||||||
attribute :rsc, :kind_of => String
|
|
||||||
attribute :with_rsc, :kind_of => String
|
|
||||||
attribute :multiple_rscs, :kind_of => Array
|
|
||||||
|
14
spec/fixtures/colocation_constraint.rb
vendored
Normal file
14
spec/fixtures/colocation_constraint.rb
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
require ::File.join(::File.dirname(__FILE__),
|
||||||
|
*%w(.. .. libraries pacemaker constraint colocation))
|
||||||
|
|
||||||
|
module Chef::RSpec
|
||||||
|
module Pacemaker
|
||||||
|
module Config
|
||||||
|
COLOCATION_CONSTRAINT = \
|
||||||
|
::Pacemaker::Constraint::Colocation.new('colocation1')
|
||||||
|
COLOCATION_CONSTRAINT.score = 'inf'
|
||||||
|
COLOCATION_CONSTRAINT.resources = ['foo']
|
||||||
|
COLOCATION_CONSTRAINT_DEFINITION = 'colocation colocation1 inf: foo'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
27
spec/libraries/pacemaker/constraint/colocation_spec.rb
Normal file
27
spec/libraries/pacemaker/constraint/colocation_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
require File.join(File.dirname(__FILE__), %w(.. .. .. ..
|
||||||
|
libraries pacemaker constraint colocation))
|
||||||
|
require File.join(File.dirname(__FILE__), %w(.. .. .. fixtures colocation_constraint))
|
||||||
|
require File.join(File.dirname(__FILE__), %w(.. .. .. helpers common_object_examples))
|
||||||
|
|
||||||
|
describe Pacemaker::Constraint::Colocation do
|
||||||
|
let(:fixture) { Chef::RSpec::Pacemaker::Config::COLOCATION_CONSTRAINT.dup }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
Mixlib::ShellOut.any_instance.stub(:run_command)
|
||||||
|
end
|
||||||
|
|
||||||
|
def object_type
|
||||||
|
'colocation'
|
||||||
|
end
|
||||||
|
|
||||||
|
def pacemaker_object_class
|
||||||
|
Pacemaker::Constraint::Colocation
|
||||||
|
end
|
||||||
|
|
||||||
|
def fields
|
||||||
|
%w(name score resources)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_should_behave_like "a CIB object"
|
||||||
|
end
|
93
spec/providers/colocation_spec.rb
Normal file
93
spec/providers/colocation_spec.rb
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
require 'chef/application'
|
||||||
|
require File.join(File.dirname(__FILE__), %w(.. spec_helper))
|
||||||
|
require File.join(File.dirname(__FILE__), %w(.. helpers common))
|
||||||
|
require File.join(File.dirname(__FILE__), %w(.. fixtures colocation_constraint))
|
||||||
|
|
||||||
|
describe "Chef::Provider::PacemakerColocation" do
|
||||||
|
# for use inside examples:
|
||||||
|
let(:colo) { Chef::RSpec::Pacemaker::Config::COLOCATION_CONSTRAINT.dup }
|
||||||
|
# for use outside examples (e.g. when invoking shared_examples)
|
||||||
|
colo = Chef::RSpec::Pacemaker::Config::COLOCATION_CONSTRAINT.dup
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
runner_opts = {
|
||||||
|
:step_into => ['pacemaker_colocation']
|
||||||
|
}
|
||||||
|
@chef_run = ::ChefSpec::Runner.new(runner_opts)
|
||||||
|
@chef_run.converge "pacemaker::default"
|
||||||
|
@node = @chef_run.node
|
||||||
|
@run_context = @chef_run.run_context
|
||||||
|
|
||||||
|
@resource = Chef::Resource::PacemakerColocation.new(colo.name, @run_context)
|
||||||
|
@resource.score colo.score
|
||||||
|
@resource.resources colo.resources.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
let (:provider) { Chef::Provider::PacemakerColocation.new(@resource, @run_context) }
|
||||||
|
|
||||||
|
def cib_object_class
|
||||||
|
Pacemaker::Constraint::Colocation
|
||||||
|
end
|
||||||
|
|
||||||
|
include Chef::RSpec::Pacemaker::Common
|
||||||
|
|
||||||
|
describe ":create action" do
|
||||||
|
def test_modify(expected_cmds)
|
||||||
|
yield
|
||||||
|
|
||||||
|
expect_definition(colo.definition_string)
|
||||||
|
|
||||||
|
provider.run_action :create
|
||||||
|
|
||||||
|
expected_cmds.each do |cmd|
|
||||||
|
expect(@chef_run).to run_execute(cmd)
|
||||||
|
end
|
||||||
|
expect(@resource).to be_updated
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should modify the constraint if it has a different score" do
|
||||||
|
echo_string = colo.definition_string.chomp.gsub('inf', '100')
|
||||||
|
echo_string.gsub!('\\') { '\\\\' }
|
||||||
|
expected_configure_cmd_args = [
|
||||||
|
"echo '#{echo_string}' | crm configure load update -"
|
||||||
|
]
|
||||||
|
test_modify(expected_configure_cmd_args) do
|
||||||
|
@resource.score '100'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should modify the constraint if it has a resource added" do
|
||||||
|
new_resource = 'bar:Stopped'
|
||||||
|
expected = colo.dup
|
||||||
|
expected.resources = expected.resources.dup + [new_resource]
|
||||||
|
echo_string = expected.definition_string.chomp
|
||||||
|
echo_string.gsub!('\\') { '\\\\' }
|
||||||
|
expected_configure_cmd_args = [
|
||||||
|
"echo '#{echo_string}' | crm configure load update -"
|
||||||
|
]
|
||||||
|
test_modify(expected_configure_cmd_args) do
|
||||||
|
@resource.resources expected.resources
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should modify the constraint if it has a different resource" do
|
||||||
|
new_resources = ['bar:Started']
|
||||||
|
colo.resources = new_resources
|
||||||
|
echo_string = colo.definition_string.chomp
|
||||||
|
echo_string.gsub!('\\') { '\\\\' }
|
||||||
|
expected_configure_cmd_args = [
|
||||||
|
"echo '#{echo_string}' | crm configure load update -"
|
||||||
|
]
|
||||||
|
test_modify(expected_configure_cmd_args) do
|
||||||
|
@resource.resources new_resources
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ":delete action" do
|
||||||
|
it_should_behave_like "action on non-existent resource", \
|
||||||
|
:delete, "crm configure delete #{colo.name}", nil
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Reference in New Issue
Block a user