1 # Run test ie with: rspec spec/unit/provider/nova_spec.rb
3 require 'puppet/util/inifile'
5 class Puppet::Provider::Nova < Puppet::Provider
11 def self.withenv(hash, &block)
13 hash.each do |name, val|
20 saved.each do |name, val|
26 return @nova_conf if @nova_conf
27 @nova_conf = Puppet::Util::IniConfig::File.new
28 @nova_conf.read(conf_filename)
32 def self.nova_credentials
33 @nova_credentials ||= get_nova_credentials
37 self.class.nova_credentials
40 def self.get_nova_credentials
41 #needed keys for authentication
42 auth_keys = ['auth_host', 'auth_port', 'auth_protocol',
43 'admin_tenant_name', 'admin_user', 'admin_password']
45 if conf and conf['keystone_authtoken'] and
46 auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
47 return Hash[ auth_keys.map \
48 { |k| [k, conf['keystone_authtoken'][k].strip] } ]
50 raise(Puppet::Error, "File: #{conf_filename} does not contain all " +
51 "required sections. Nova types will not work if nova is not " +
52 "correctly configured.")
56 def self.get_auth_endpoint
58 "#{q['auth_protocol']}://#{q['auth_host']}:#{q['auth_port']}/v2.0/"
61 def self.auth_endpoint
62 @auth_endpoint ||= get_auth_endpoint
65 def self.auth_nova(*args)
68 :OS_AUTH_URL => self.auth_endpoint,
69 :OS_USERNAME => q['admin_user'],
70 :OS_TENANT_NAME => q['admin_tenant_name'],
71 :OS_PASSWORD => q['admin_password']
78 if (e.message =~ /\[Errno 111\] Connection refused/) or
79 (e.message =~ /\(HTTP 400\)/)
91 self.class.auth_nova(args)
96 @nova_credentials = nil
102 k, v = s.split("=", 2)
103 return {k.gsub(/'/, "") => v.gsub(/'/, "")}
105 return s.gsub(/'/, "")
117 s.split(",").each do |el|
118 ret = str2hash(el.strip())
127 return str2hash(s.strip())
131 def self.cliout2list(output)
132 #don't proceed with empty output
137 output.each_line do |line|
138 #ignore lines starting with '+'
139 if not line.match("^\\+")
140 #split line at '|' and remove useless information
141 line = line.gsub(/^\| /, "").gsub(/ \|$/, "").gsub(/[\n]+/, "")
142 line = line.split("|").map do |el|
143 el.strip().gsub(/^-$/, "")
145 #check every element for list
146 line = line.map do |el|
152 #create a list of hashes and return the list
155 lines[1..-1].each do |line|
156 hash_list.push(Hash[header.zip(line)])
161 def self.nova_aggregate_resources_ids
162 #produce a list of hashes with Id=>Name pairs
165 cmd_output = auth_nova("aggregate-list")
167 hash_list = cliout2list(cmd_output)
168 #only interessted in Id and Name
169 hash_list.map{ |e| e.delete("Availability Zone")}
170 hash_list.map{ |e| e['Id'] = e['Id'].to_i}
174 def self.nova_aggregate_resources_get_name_by_id(name)
175 #find the id by the given name
176 nova_aggregate_resources_ids.each do |entry|
177 if entry["Name"] == name
185 def self.nova_aggregate_resources_attr(id)
186 #run command to get details for given Id
187 cmd_output = auth_nova("aggregate-details", id)
188 list = cliout2list(cmd_output)[0]
189 if ! list["Hosts"].is_a?(Array)
190 if list["Hosts"] == ""
193 list["Hosts"] = [ list["Hosts"] ]