require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/nova') Puppet::Type.type(:nova_aggregate).provide( :nova, :parent => Puppet::Provider::Nova ) do desc "Manage nova aggregations" commands :nova => 'nova' mk_resource_methods def self.instances nova_aggregate_resources_ids().collect do |el| attrs = nova_aggregate_resources_attr(el['Id']) new( :ensure => :present, :name => attrs['Name'], :id => attrs['Id'], :availability_zone => attrs['Availability Zone'], :metadata => attrs['Metadata'], :hosts => attrs['Hosts'] ) end end def self.prefetch(resources) instances_ = instances resources.keys.each do |name| if provider = instances_.find{ |instance| instance.name == name } resources[name].provider = provider end end end def exists? @property_hash[:ensure] == :present end def destroy #delete hosts first if not @property_hash[:hosts].nil? @property_hash[:hosts].each do |h| auth_nova("aggregate-remove-host", name, h) end end #now delete aggregate auth_nova("aggregate-delete", name) @property_hash[:ensure] = :absent end def create extras = Array.new #check for availability zone if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty? extras << "#{@resource[:availability_zone]}" end #run the command result = auth_nova("aggregate-create", resource[:name], extras) #get Id by Name id = self.class.nova_aggregate_resources_get_name_by_id(resource[:name]) @property_hash = { :ensure => :present, :name => resource[:name], :id => id, :availability_zone => resource[:availability_zone] } #add metadata if not @resource[:metadata].nil? and not @resource[:metadata].empty? @resource[:metadata].each do |key, value| set_metadata_helper(id, key, value) end @property_hash[:metadata] = resource[:metadata] end #add hosts - This throws an error if the host is already attached to another aggregate! if not @resource[:hosts].nil? and not @resource[:hosts].empty? @resource[:hosts].each do |host| auth_nova("aggregate-add-host", id, "#{host}") end @property_hash[:hosts] = resource[:hosts] end end def hosts=(val) #get current hosts id = self.class.nova_aggregate_resources_get_name_by_id(name) attrs = self.class.nova_aggregate_resources_attr(id) #remove all hosts which are not in new value list attrs['Hosts'].each do |h| if not val.include? h auth_nova("aggregate-remove-host", id, "#{h}") end end #add hosts from the value list val.each do |h| if not attrs['Hosts'].include? h auth_nova("aggregate-add-host", id, "#{h}") end end end def set_metadata_helper(agg_id, key, value) auth_nova("aggregate-set-metadata", agg_id, "#{key}=#{value}") end def metadata #get current metadata id = self.class.nova_aggregate_resources_get_name_by_id(name) attrs = self.class.nova_aggregate_resources_attr(id) #just ignore the availability_zone. that's handled directly by nova attrs['Metadata'].delete('availability_zone') return attrs['Metadata'] end def metadata=(val) #get current metadata id = self.class.nova_aggregate_resources_get_name_by_id(name) attrs = self.class.nova_aggregate_resources_attr(id) #get keys which are in current metadata but not in val. Make sure it has data first! if attrs['Metadata'].length > 0 obsolete_keys = attrs['Metadata'].keys - val.keys end # clear obsolete keys. If there are any! if obsolete_keys obsolete_keys.each do |key| if not key.include? 'availability_zone' auth_nova("aggregate-set-metadata", id, "#{key}") end end #handle keys (with obsolete keys) new_keys = val.keys - obsolete_keys else #handle keys (without obsolete keys) new_keys = val.keys end #set new metadata if value changed new_keys.each do |key| if val[key] != attrs['Metadata'][key.to_s] value = val[key] set_metadata_helper(id, key, value) end end end def availability_zone=(val) id = self.class.nova_aggregate_resources_get_name_by_id(name) auth_nova("aggregate-set-metadata", id, "availability_zone=#{val}") end end