]> git.donarmstrong.com Git - dsa-puppet.git/blobdiff - 3rdparty/modules/nova/lib/puppet/provider/nova.rb
try again, with puppetforge modules, correctly included now
[dsa-puppet.git] / 3rdparty / modules / nova / lib / puppet / provider / nova.rb
diff --git a/3rdparty/modules/nova/lib/puppet/provider/nova.rb b/3rdparty/modules/nova/lib/puppet/provider/nova.rb
new file mode 100644 (file)
index 0000000..ca7bb01
--- /dev/null
@@ -0,0 +1,199 @@
+# Run test ie with: rspec spec/unit/provider/nova_spec.rb
+
+require 'puppet/util/inifile'
+
+class Puppet::Provider::Nova < Puppet::Provider
+
+  def self.conf_filename
+    '/etc/nova/nova.conf'
+  end
+
+  def self.withenv(hash, &block)
+    saved = ENV.to_hash
+    hash.each do |name, val|
+      ENV[name.to_s] = val
+    end
+
+    yield
+  ensure
+    ENV.clear
+    saved.each do |name, val|
+      ENV[name] = val
+    end
+  end
+
+  def self.nova_conf
+    return @nova_conf if @nova_conf
+    @nova_conf = Puppet::Util::IniConfig::File.new
+    @nova_conf.read(conf_filename)
+    @nova_conf
+  end
+
+  def self.nova_credentials
+    @nova_credentials ||= get_nova_credentials
+  end
+
+  def nova_credentials
+    self.class.nova_credentials
+  end
+
+  def self.get_nova_credentials
+    #needed keys for authentication
+    auth_keys = ['auth_host', 'auth_port', 'auth_protocol',
+                 'admin_tenant_name', 'admin_user', 'admin_password']
+    conf = nova_conf
+    if conf and conf['keystone_authtoken'] and
+        auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
+      return Hash[ auth_keys.map \
+                   { |k| [k, conf['keystone_authtoken'][k].strip] } ]
+    else
+      raise(Puppet::Error, "File: #{conf_filename} does not contain all " +
+            "required sections.  Nova types will not work if nova is not " +
+            "correctly configured.")
+    end
+  end
+
+  def self.get_auth_endpoint
+    q = nova_credentials
+    "#{q['auth_protocol']}://#{q['auth_host']}:#{q['auth_port']}/v2.0/"
+  end
+
+  def self.auth_endpoint
+    @auth_endpoint ||= get_auth_endpoint
+  end
+
+  def self.auth_nova(*args)
+    q = nova_credentials
+    authenv = {
+      :OS_AUTH_URL    => self.auth_endpoint,
+      :OS_USERNAME    => q['admin_user'],
+      :OS_TENANT_NAME => q['admin_tenant_name'],
+      :OS_PASSWORD    => q['admin_password']
+    }
+    begin
+      withenv authenv do
+        nova(args)
+      end
+    rescue Exception => e
+      if (e.message =~ /\[Errno 111\] Connection refused/) or
+          (e.message =~ /\(HTTP 400\)/)
+        sleep 10
+        withenv authenv do
+          nova(args)
+        end
+      else
+       raise(e)
+      end
+    end
+  end
+
+  def auth_nova(*args)
+    self.class.auth_nova(args)
+  end
+
+  def self.reset
+    @nova_conf = nil
+    @nova_credentials = nil
+  end
+
+  def self.str2hash(s)
+    #parse string
+    if s.include? "="
+      k, v = s.split("=", 2)
+      return {k.gsub(/'/, "") => v.gsub(/'/, "")}
+    else
+      return s.gsub(/'/, "")
+    end
+  end
+
+  def self.str2list(s)
+    #parse string
+    if s.include? ","
+      if s.include? "="
+        new = {}
+      else
+        new = []
+      end
+      s.split(",").each do |el|
+        ret = str2hash(el.strip())
+        if s.include? "="
+          new.update(ret)
+        else
+          new.push(ret)
+        end
+      end
+      return new
+    else
+      return str2hash(s.strip())
+    end
+  end
+
+  def self.cliout2list(output)
+    #don't proceed with empty output
+    if output.empty?
+      return []
+    end
+    lines = []
+    output.each_line do |line|
+      #ignore lines starting with '+'
+      if not line.match("^\\+")
+        #split line at '|' and remove useless information
+        line = line.gsub(/^\| /, "").gsub(/ \|$/, "").gsub(/[\n]+/, "")
+        line = line.split("|").map do |el|
+          el.strip().gsub(/^-$/, "")
+        end
+        #check every element for list
+        line = line.map do |el|
+          el = str2list(el)
+        end
+        lines.push(line)
+      end
+    end
+    #create a list of hashes and return the list
+    hash_list = []
+    header = lines[0]
+    lines[1..-1].each do |line|
+      hash_list.push(Hash[header.zip(line)])
+    end
+    return hash_list
+  end
+
+  def self.nova_aggregate_resources_ids
+    #produce a list of hashes with Id=>Name pairs
+    lines = []
+    #run command
+    cmd_output = auth_nova("aggregate-list")
+    #parse output
+    hash_list = cliout2list(cmd_output)
+    #only interessted in Id and Name
+    hash_list.map{ |e| e.delete("Availability Zone")}
+    hash_list.map{ |e| e['Id'] = e['Id'].to_i}
+  return hash_list
+  end
+
+  def self.nova_aggregate_resources_get_name_by_id(name)
+    #find the id by the given name
+    nova_aggregate_resources_ids.each do |entry|
+      if entry["Name"] == name
+        return entry["Id"]
+      end
+    end
+    #name not found
+    return nil
+  end
+
+  def self.nova_aggregate_resources_attr(id)
+    #run command to get details for given Id
+    cmd_output = auth_nova("aggregate-details", id)
+    list = cliout2list(cmd_output)[0]
+    if ! list["Hosts"].is_a?(Array)
+      if list["Hosts"] == ""
+        list["Hosts"] = []
+      else
+        list["Hosts"] = [ list["Hosts"] ]
+      end
+    end
+    return list
+  end
+
+end