1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
# provider for swift_storage_policy resource.
#
Puppet::Type.type(:swift_storage_policy).provide(:ruby) do
mk_resource_methods
# Policy indexes must be unique, the storage policy resource name is its ID.
# Storage policy section headings in swift.conf are of the format "storage-policy:<policy ID>
def policy_title
"storage-policy:#{name}"
end
def create
@property_flush[:ensure] = :present
end
def destroy
@property_flush[:ensure] = :absent
end
def exists?
# If a storage policy exists if it is ensured absent and is also found in swift.conf.
if (resource[:ensure] == :absent) &&
(self.class.storage_policies.include? policy_title)
return true
end
if self.class.storage_policies.include? policy_title
# Return false if settings are removed from swift.conf that do not exist in the puppet resource.
# This resource will then update swift.conf in flush.
return false if remove_storage_policy_settings?
end
@property_hash[:ensure] == :present
end
def flush
# flush is called when policy state in swift.conf does not match what is defined in puppet.
# get all resource settings and store in @property_flush for use in write_policy
# @property_flush is the state the policy should be in.
# @property_hash is the state of the policy in swift.conf
self.class.policy_settings.each do |property_name, _|
@property_flush[property_name] = resource[property_name]
end
# If this policy is set to absent, call write_policy to remove it from swift.conf.
if @property_flush[:ensure] == :absent
write_policy
return
end
# At this point, this is a new policy to write to disk. Or this is a policy
# containing a setting that needs to be updated on disk.
# Write this policy unless:
# - a policy on disk already has this same policy_name or aliases.
# or a policy default setting conflict is found.
if !self.class.instances.empty?
write_policy unless policy_names_conflict? ||
default_policy_defined?
else
write_policy
end
@property_hash = self.class.storage_policy_properties(policy_title)
end
# A hash of property_name => setting_name. property_name used to access
# resource properties. setting_name used in swift.conf storage policy setting.
def self.policy_settings
settings_hash = { policy_name: 'name',
aliases: 'aliases',
policy_type: 'policy_type',
deprecated: 'deprecated',
default: 'default',
ec_type: 'ec_type',
ec_num_data_fragments: 'ec_num_data_fragments',
ec_num_parity_fragments: 'ec_num_parity_fragments',
ec_object_segment_size: 'ec_object_segment_size' }
settings_hash
end
# Read storage policies from disk found in swift.conf
def self.storage_policies
policies = []
config.section_names.each do |section_name|
policies.push(section_name) if section_name.start_with?('storage-policy')
end
policies.sort
policies
end
# Read storage policy settings and values found swift.conf
def self.storage_policy_properties(policy)
policy_properties = {}
policy_properties[:provider] = :ruby
policy_properties[:name] = policy.split(':')[1]
policy_properties[:ensure] = :present
policy_settings.each do |property_name, setting_name|
unless config.get_value(policy, setting_name).nil?
policy_properties[property_name] = config.get_value(policy, setting_name)
end
end
policy_properties
end
def write_policy
if @property_flush[:ensure] == :absent
remove_storage_policy_section
return
end
self.class.policy_settings.each do |property_name, setting_name|
unless @property_flush[property_name].nil?
config.set_value(policy_title, setting_name, '=', @property_flush[property_name])
end
end
config.save
@config = nil
end
# Removes the entire storage policy section header and settings for this instance.
# TODO push a 'remove_section' method into puppet inifile module for the ini_file util.
def remove_storage_policy_section
# Get all settings for this storage policy section and remove them.
@sections = config.instance_variable_get(:@sections_hash)
@sections[policy_title].instance_variable_get(:@existing_settings).each do |setting, _|
config.remove_setting(policy_title, setting)
end
# ini_file tracks an array of section names 'section_names' and a hash of sections 'sections_hash'
# get array of section names and delete this storage policy from it.
@section_names = config.instance_variable_get(:@section_names)
@section_names.delete(policy_title)
# delete the entire section from the sections_hash then save swift.conf
@sections.delete(policy_title)
config.save
end
# Check for storage policy settings found in swift.conf that are not defined
# in puppet and should be removed from the policy. Return True if settings
# were removed. Removing a setting from a policy declaration will remove that
# setting from swift.conf
def remove_storage_policy_settings?
settings_removed = false
# If storage policy settings are found in swift.conf that are not defined,
# remove the setting line.
self.class.storage_policy_properties(policy_title).each do |key, value|
next unless @resource[key] != value
config.remove_setting(policy_title, key.to_s.delete(':'))
config.save
settings_removed = true
end
@config = nil
settings_removed
end
# Compare current policy alias against existing storage policies in swift.conf
# Duplicate alias are not allowed.
def policy_names_conflict?
self.class.instances.each do |policy|
next if policy.policy_title.eql? "storage-policy:#{name}"
# Split policy aliases into an array and add policy name.
# Split resource aliases into an array and add resource policy_name.
# If any intersecting elements exist raise an error alerting on the
# attempt to set a duplicate name/alias.
policy_names = policy.policy_name.split
unless policy.aliases == :absent
policy_names = policy.aliases.split(', ').concat policy.policy_name.split
end
resource_names = resource[:policy_name].split
unless resource[:aliases].nil?
resource_names = resource[:aliases].split(', ').concat resource[:policy_name].split
end
alias_intersection = policy_names & resource_names
next if alias_intersection.empty?
raise Puppet::Error, "Swift_storage_policy[#{resource[:name]}] trying "\
"to set a duplicate name/alias:#{alias_intersection},"\
"this name/alias exists in #{policy.policy_title}\n"
end
false
end
# Check storage policy default settings across resources to verify that:
# - If any policies are defined, exactly one policy must be declared default.
# - Only one policy can be declared the default.
def default_policy_defined?
self.class.instances.each do |policy|
# Don't compare this instance with its copy found on disk.
next if (policy.policy_title.eql? "storage-policy:#{name}") ||
(policy.default == 'false')
case resource[:default]
when 'true'
raise Puppet::Error, "Swift_storage_policy[#{resource[:name]}] can "\
'not set default = true. '\
"default=true already set in a policy #{policy.policy_title}\n"
when 'false'
return false
end
end
return unless resource[:default] == 'false'
raise Puppet::Error, 'All storage policies have set default = false.. '\
'exactly one policy must be declared default = true'
end
def self.instances
storage_policies.collect do |policy|
policy_properties = storage_policy_properties(policy)
new(policy_properties)
end
end
def self.prefetch(resources)
instances.each do |prov|
if resource = resources[prov.name]
resource.provider = prov
end
end
end
def initialize(value = {})
super(value)
@property_flush = {}
end
private
def self.get_swift_conf_file
if File.exist? '/etc/swift/swift.conf'
file = '/etc/swift/swift.conf'
else
file = '/etc/swift/swift.conf'
end
file
end
def config
self.class.config
end
def self.config
@config ||= Puppet::Util::IniFile.new(get_swift_conf_file)
end
end
|