diff --git a/attributes/default.rb b/attributes/default.rb index 3d1c376..adbba1a 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -32,5 +32,22 @@ end default[:pacemaker][:founder] = false default[:pacemaker][:crm][:initial_config_file] = "/etc/corosync/crm-initial.conf" -default[:pacemaker][:crm][:stonith_enabled] = false default[:pacemaker][:crm][:no_quorum_policy] = "ignore" + +# Values can be "disabled", "manual", "clone", "per_node" +default[:pacemaker][:stonith][:mode] = "disabled" + +default[:pacemaker][:stonith][:clone][:plugin] = "" +# This can be either a string (containing a list of parameters) or a hash. +# For instance: +# default[:pacemaker][:stonith][:clone][:params] = 'hostname="foo" password="bar"' +# will give the same result as: +# default[:pacemaker][:stonith][:clone][:params] = {"hostname" => "foo", "password" => "bar"} +default[:pacemaker][:stonith][:clone][:params] = {} + +default[:pacemaker][:stonith][:per_node][:plugin] = "" +# This hash will contain parameters for each node. See documentation for +# default[:pacemaker][:stonith][:clone][:params] about the format. +# For instance: +# default[:pacemaker][:stonith][:per_node][:nodes][$node][:params] = 'hostname="foo" password="bar"' +default[:pacemaker][:stonith][:per_node][:nodes] = {} diff --git a/recipes/default.rb b/recipes/default.rb index 74893f8..3258f33 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -61,3 +61,5 @@ if platform_family? "rhel" notifies :restart, "service[clvm]", :immediately end end + +include_recipe "pacemaker::stonith" diff --git a/recipes/setup.rb b/recipes/setup.rb index df4f924..a806014 100644 --- a/recipes/setup.rb +++ b/recipes/setup.rb @@ -26,7 +26,7 @@ template crm_conf do group "root" mode 0600 variables( - :stonith_enabled => node[:pacemaker][:crm][:stonith_enabled], + :stonith_enabled => (node[:pacemaker][:stonith][:mode] != "disabled"), :no_quorum_policy => node[:pacemaker][:crm][:no_quorum_policy] ) end diff --git a/recipes/stonith.rb b/recipes/stonith.rb new file mode 100644 index 0000000..56db368 --- /dev/null +++ b/recipes/stonith.rb @@ -0,0 +1,102 @@ +# +# Author:: Vincent Untz +# Cookbook Name:: pacemaker +# Recipe:: stonith +# +# 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. +# + +# FIXME: delete old resources when switching mode (or plugin!) +# FIXME: check that the stonith plugin to use exists with stonith -L + +case node[:pacemaker][:stonith][:mode] +when "disabled" +when "manual" + # nothing! + +when "clone" + plugin = node[:pacemaker][:stonith][:clone][:plugin] + params = node[:pacemaker][:stonith][:clone][:params] + + if params.respond_to?('to_hash') + primitive_params = params.to_hash + elsif params.is_a?(String) + primitive_params = ::Pacemaker::Resource.extract_hash("params #{params}", "params") + else + message = "Unknown format for STONITH clone parameters: #{params.inspect}." + Chef::Log.fatal(message) + raise message + end + + unless primitive_params.has_key?("hostlist") + message = "Missing hostlist parameter for STONITH clone!" + Chef::Log.fatal(message) + raise message + end + + pacemaker_primitive "stonith-clone" do + agent "stonith:#{plugin}" + params primitive_params + action :create + end + + pacemaker_clone "fencing" do + rsc "stonith-clone" + action :create + end + +when "per_node" + plugin = node[:pacemaker][:stonith][:per_node][:plugin] + + node[:pacemaker][:stonith][:per_node][:nodes].keys.each do |node_name| + stonith_resource = "stonith-#{node_name}" + params = node[:pacemaker][:stonith][:per_node][:nodes][node_name][:params] + + if params.respond_to?('to_hash') + primitive_params = params.to_hash + elsif params.is_a?(String) + primitive_params = ::Pacemaker::Resource.extract_hash("params #{params}", "params") + else + message = "Unknown format for STONITH per-node parameters of #{node_name}: #{params.inspect}." + Chef::Log.fatal(message) + raise message + end + + # Only set hostlist param if it's missing; we do not overwrite it as the + # user might have passed more information than just the hostname (some + # plugins accept hostname:data in hostlist) + unless primitive_params.has_key?("hostlist") + primitive_params["hostlist"] = node_name + end + + pacemaker_primitive stonith_resource do + agent "stonith:#{plugin}" + params primitive_params + action :create + end + + pacemaker_location "l-#{stonith_resource}" do + rsc stonith_resource + score "-inf" + node node_name + action :create + end + end + +else + message = "Unknown STONITH mode: #{node[:pacemaker][:stonith][:mode]}." + Chef::Log.fatal(message) + raise message +end