add resource groups

This commit is contained in:
Adam Spiers 2014-02-04 17:42:21 +00:00
parent 012c70f6dc
commit f127600a60
7 changed files with 300 additions and 0 deletions

View File

@ -1,3 +1,4 @@
require File.expand_path('pacemaker/resource/primitive', File.dirname(__FILE__))
require File.expand_path('pacemaker/resource/clone', File.dirname(__FILE__))
require File.expand_path('pacemaker/resource/group', File.dirname(__FILE__))
require File.expand_path('pacemaker/constraint/colocation', File.dirname(__FILE__))

View File

@ -0,0 +1,43 @@
require File.expand_path('../resource', File.dirname(__FILE__))
require File.expand_path('../mixins/resource_meta', File.dirname(__FILE__))
class Pacemaker::Resource::Group < Pacemaker::Resource
TYPE = 'group'
register_type TYPE
include Pacemaker::Resource::Meta
attr_accessor :members
def self.from_chef_resource(resource)
attrs = %w(members meta)
new(resource.name).copy_attrs_from_chef_resource(resource, *attrs)
end
def parse_definition
rsc_re = /(\S+?)(?::(Started|Stopped))?/
unless definition =~ /^#{TYPE} (\S+) (.+?)(\s+\\)?$/
raise Pacemaker::CIBObject::DefinitionParseError, \
"Couldn't parse definition '#{definition}'"
end
self.name = $1
members = $2.split
trim_from = members.find_index('meta')
members = members[0..trim_from-1] if trim_from
self.members = members
self.meta = self.class.extract_hash(definition, 'meta')
end
def definition_string
str = "#{TYPE} #{name} " + members.join(' ')
unless meta.empty?
str << continuation_line(meta_string)
end
str
end
def crm_configure_command
"crm configure " + definition_string
end
end

78
providers/group.rb Normal file
View File

@ -0,0 +1,78 @@
# Cookbook Name:: pacemaker
# Provider:: group
#
# Copyright:: 2014, SUSE
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__))
require ::File.expand_path('../libraries/chef/mixin/pacemaker',
::File.dirname(__FILE__))
include Chef::Mixin::Pacemaker::RunnableResource
action :create do
name = new_resource.name
if @current_resource_definition.nil?
create_resource(name)
else
maybe_modify_resource(name)
end
end
action :delete do
delete_runnable_resource
end
action :start do
start_runnable_resource
end
action :stop do
stop_runnable_resource
end
def cib_object_class
::Pacemaker::Resource::Group
end
def load_current_resource
standard_load_current_resource
end
def init_current_resource
name = @new_resource.name
@current_resource = Chef::Resource::PacemakerGroup.new(name)
attrs = [:members]
@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_group = cib_object_class.from_chef_resource(new_resource)
if desired_group.definition_string != @current_cib_object.definition_string
Chef::Log.debug "changed from [#{@current_cib_object.definition_string}] to [#{desired_group.definition_string}]"
cmd = desired_group.reconfigure_command
execute cmd do
action :nothing
end.run_action(:run)
new_resource.updated_by_last_action(true)
end
end

25
resources/group.rb Normal file
View File

@ -0,0 +1,25 @@
# Cookbook Name:: pacemaker
# Resource:: group
#
# Copyright:: 2014, SUSE
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
actions :create, :delete, :start, :stop
default_action :create
attribute :name, :kind_of => String, :name_attribute => true
attribute :members, :kind_of => Array
attribute :meta, :kind_of => Hash

20
spec/fixtures/resource_group.rb vendored Normal file
View File

@ -0,0 +1,20 @@
require File.expand_path('../../libraries/pacemaker/resource/group',
File.dirname(__FILE__))
module Chef::RSpec
module Pacemaker
module Config
RESOURCE_GROUP = \
::Pacemaker::Resource::Group.new('group1')
RESOURCE_GROUP.members = ['resource1', 'resource2']
RESOURCE_GROUP.meta = [
[ "target-role", "Started" ],
[ "is-managed", "true" ]
]
RESOURCE_GROUP_DEFINITION = <<'EOF'.chomp
group group1 resource1 resource2 \
meta is-managed="true" target-role="Started"
EOF
end
end
end

View File

@ -0,0 +1,63 @@
require 'spec_helper'
require File.expand_path('../../../../libraries/pacemaker/resource/group',
File.dirname(__FILE__))
require File.expand_path('../../../fixtures/resource_group', File.dirname(__FILE__))
require File.expand_path('../../../helpers/cib_object', File.dirname(__FILE__))
require File.expand_path('../../../helpers/meta_examples',
File.dirname(__FILE__))
describe Pacemaker::Resource::Group do
let(:fixture) { Chef::RSpec::Pacemaker::Config::RESOURCE_GROUP.dup }
let(:fixture_definition) {
Chef::RSpec::Pacemaker::Config::RESOURCE_GROUP_DEFINITION
}
before(:each) do
Mixlib::ShellOut.any_instance.stub(:run_command)
end
def object_type
'group'
end
def pacemaker_object_class
Pacemaker::Resource::Group
end
def fields
%w(name members)
end
it_should_behave_like "a CIB object"
it_should_behave_like "with meta attributes"
describe "#definition_string" do
it "should return the definition string" do
expect(fixture.definition_string).to eq(fixture_definition)
end
it "should return a short definition string" do
primitive = Pacemaker::Resource::Group.new('foo')
primitive.definition = \
%!group foo member1 member2 meta target-role="Started"!
primitive.parse_definition
expect(primitive.definition_string).to eq(<<'EOF'.chomp)
group foo member1 member2 \
meta target-role="Started"
EOF
end
end
describe "#parse_definition" do
before(:each) do
@parsed = Pacemaker::Resource::Group.new(fixture.name)
@parsed.definition = fixture_definition
@parsed.parse_definition
end
it "should parse the members" do
expect(@parsed.members).to eq(fixture.members)
end
end
end

View File

@ -0,0 +1,70 @@
require 'chef/application'
require File.expand_path('../spec_helper', File.dirname(__FILE__))
require File.expand_path('../helpers/cib_object', File.dirname(__FILE__))
require File.expand_path('../helpers/runnable_resource', File.dirname(__FILE__))
require File.expand_path('../fixtures/resource_group', File.dirname(__FILE__))
describe "Chef::Provider::PacemakerGroup" do
# for use inside examples:
let(:fixture) { Chef::RSpec::Pacemaker::Config::RESOURCE_GROUP.dup }
# for use outside examples (e.g. when invoking shared_examples)
fixture = Chef::RSpec::Pacemaker::Config::RESOURCE_GROUP.dup
before(:each) do
runner_opts = {
:step_into => ['pacemaker_group']
}
@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::PacemakerGroup.new(fixture.name, @run_context)
@resource.members fixture.members.dup
@resource.meta Hash[fixture.meta.dup]
end
let (:provider) { Chef::Provider::PacemakerGroup.new(@resource, @run_context) }
def cib_object_class
Pacemaker::Resource::Group
end
include Chef::RSpec::Pacemaker::CIBObject
describe ":create action" do
def test_modify(expected_cmds)
yield
expect_definition(fixture.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 group if it has a member resource added" do
expected = fixture.dup
expected.members = expected.members.dup + %w(resource3)
expected_configure_cmd_args = [expected.reconfigure_command]
test_modify(expected_configure_cmd_args) do
@resource.members expected.members
end
end
it "should modify the group if it has different member resources" do
fixture.members = %w(resource1 resource3)
expected_configure_cmd_args = [fixture.reconfigure_command]
test_modify(expected_configure_cmd_args) do
@resource.members fixture.members
end
end
end
it_should_behave_like "a runnable resource", fixture
end