require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/nova') Puppet::Type.type(:nova_aggregate).provide( :openstack, :parent => Puppet::Provider::Nova ) do desc <<-EOT Provider to manage nova aggregations EOT @credentials = Puppet::Provider::Openstack::CredentialsV3.new mk_resource_methods def self.instances request('aggregate', 'list').collect do |el| attrs = request('aggregate', 'show', el[:name]) properties = parsestring(attrs[:properties]) rescue nil new( :ensure => :present, :name => attrs[:name], :id => attrs[:id], :availability_zone => attrs[:availability_zone], :metadata => properties, :hosts => string2list(attrs[:hosts]).sort, :filter_hosts => attrs[:filter_hosts] ) end end def self.string2list(input) return input[1..-2].split(",").map { |x| x.match(/'(.*?)'/)[1] } 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 self.get_known_hosts # get list of hosts known to be active from openstack return request('compute service', 'list', ['--service', 'nova-compute']).map{|el| el[:host]} end def exists? @property_hash[:ensure] == :present end def destroy @property_hash[:hosts].each do |h| properties = [@property_hash[:name], h] self.class.request('aggregate', 'remove host', properties) end self.class.request('aggregate', 'delete', @property_hash[:name]) @property_hash.clear end def create properties = [@resource[:name]] if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty? properties << "--zone" << @resource[:availability_zone] end if not @resource[:metadata].nil? and not @resource[:metadata].empty? @resource[:metadata].each do |key, value| properties << "--property" << "#{key}=#{value}" end end @property_hash = self.class.request('aggregate', 'create', properties) if not @resource[:hosts].nil? and not @resource[:hosts].empty? # filter host list by known hosts if filter_hosts is set if @resource[:filter_hosts] == :true @resource[:hosts] = @resource[:hosts] & self.class.get_known_hosts() end @resource[:hosts].each do |host| properties = [@property_hash[:name], host] self.class.request('aggregate', 'add host', properties) end end @property_hash[:ensure] = :present end def availability_zone=(value) self.class.request('aggregate', 'set', [ @resource[:name], '--zone', @resource[:availability_zone] ]) end def metadata=(value) # clear obsolete keys if @property_hash[:metadata].keys.length > 0 properties = [@resource[:name] ] (@property_hash[:metadata].keys - @resource[:metadata].keys).each do |key| properties << "--property" << "#{key}" end self.class.request('aggregate', 'unset', properties) end properties = [@resource[:name] ] @resource[:metadata].each do |key, value| properties << "--property" << "#{key}=#{value}" end self.class.request('aggregate', 'set', properties) end def hosts=(value) # filter host list by known hosts if filter_hosts is set if @resource[:filter_hosts] == :true value &= self.class.get_known_hosts() end if not @property_hash[:hosts].nil? # remove hosts that are not present in update (@property_hash[:hosts] - value).each do |host| self.class.request('aggregate', 'remove host', [@property_hash[:id], host]) end # add hosts that are not already present (value - @property_hash[:hosts]).each do |host| self.class.request('aggregate', 'add host', [@property_hash[:id], host]) end end end def self.string2hash(input) return Hash[input.scan(/(\S+)='([^']*)'/)] end def self.pythondict2hash(input) return JSON.parse(input.gsub(/'/, '"')) end def self.parsestring(input) if input[0] == '{' # 4.0.0+ output, python dict return self.pythondict2hash(input) else # Pre-4.0.0 output, key=value return self.string2hash(input) end end end