File: ruby.rb

package info (click to toggle)
puppet-module-swift 27.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,480 kB
  • sloc: ruby: 9,604; python: 33; makefile: 10; sh: 10
file content (235 lines) | stat: -rw-r--r-- 8,777 bytes parent folder | download
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