+++ /dev/null
-# Since there's only one glance type for now,
-# this probably could have all gone in the provider file.
-# But maybe this is good long-term.
-require 'puppet/util/inifile'
-class Puppet::Provider::Glance < Puppet::Provider
-
- def self.glance_credentials
- @glance_credentials ||= get_glance_credentials
- end
-
- def self.get_glance_credentials
- if glance_file and glance_file['keystone_authtoken'] and
- glance_file['keystone_authtoken']['auth_host'] and
- glance_file['keystone_authtoken']['auth_port'] and
- glance_file['keystone_authtoken']['auth_protocol'] and
- glance_file['keystone_authtoken']['admin_tenant_name'] and
- glance_file['keystone_authtoken']['admin_user'] and
- glance_file['keystone_authtoken']['admin_password'] and
- glance_file['DEFAULT']['os_region_name']
-
- g = {}
- g['auth_host'] = glance_file['keystone_authtoken']['auth_host'].strip
- g['auth_port'] = glance_file['keystone_authtoken']['auth_port'].strip
- g['auth_protocol'] = glance_file['keystone_authtoken']['auth_protocol'].strip
- g['admin_tenant_name'] = glance_file['keystone_authtoken']['admin_tenant_name'].strip
- g['admin_user'] = glance_file['keystone_authtoken']['admin_user'].strip
- g['admin_password'] = glance_file['keystone_authtoken']['admin_password'].strip
- g['os_region_name'] = glance_file['DEFAULT']['os_region_name'].strip
-
- # auth_admin_prefix not required to be set.
- g['auth_admin_prefix'] = (glance_file['keystone_authtoken']['auth_admin_prefix'] || '').strip
-
- return g
- else
- raise(Puppet::Error, 'File: /etc/glance/glance-api.conf does not contain all required sections.')
- end
- end
-
- def glance_credentials
- self.class.glance_credentials
- end
-
- def self.auth_endpoint
- @auth_endpoint ||= get_auth_endpoint
- end
-
- def self.get_auth_endpoint
- g = glance_credentials
- "#{g['auth_protocol']}://#{g['auth_host']}:#{g['auth_port']}#{g['auth_admin_prefix']}/v2.0/"
- end
-
- def self.glance_file
- return @glance_file if @glance_file
- @glance_file = Puppet::Util::IniConfig::File.new
- @glance_file.read('/etc/glance/glance-api.conf')
- @glance_file
- end
-
- def self.glance_hash
- @glance_hash ||= build_glance_hash
- end
-
- def self.reset
- @glance_hash = nil
- @glance_file = nil
- @glance_credentials = nil
- @auth_endpoint = nil
- end
-
- def glance_hash
- self.class.glance_hash
- end
-
- def self.auth_glance(*args)
- begin
- g = glance_credentials
- remove_warnings(glance('--os-tenant-name', g['admin_tenant_name'], '--os-username', g['admin_user'], '--os-password', g['admin_password'], '--os-region-name', g['os_region_name'], '--os-auth-url', auth_endpoint, args))
- rescue Exception => e
- if (e.message =~ /\[Errno 111\] Connection refused/) or (e.message =~ /\(HTTP 400\)/) or (e.message =~ /HTTP Unable to establish connection/)
- sleep 10
- remove_warnings(glance('--os-tenant-name', g['admin_tenant_name'], '--os-username', g['admin_user'], '--os-password', g['admin_password'], '--os-region-name', g['os_region_name'], '--os-auth-url', auth_endpoint, args))
- else
- raise(e)
- end
- end
- end
-
- def auth_glance(*args)
- self.class.auth_glance(args)
- end
-
- def self.auth_glance_stdin(*args)
- begin
- g = glance_credentials
- command = "glance --os-tenant-name #{g['admin_tenant_name']} --os-username #{g['admin_user']} --os-password #{g['admin_password']} --os-region-name #{g['os_region_name']} --os-auth-url #{auth_endpoint} #{args.join(' ')}"
-
- # This is a horrible, horrible hack
- # Redirect stderr to stdout in order to report errors
- # Ignore good output
- err = `#{command} 3>&1 1>/dev/null 2>&3`
- if $? != 0
- raise(Puppet::Error, err)
- end
- end
- end
-
- def auth_glance_stdin(*args)
- self.class.auth_glance_stdin(args)
- end
-
- private
- def self.list_glance_images
- ids = []
- (auth_glance('image-list').split("\n")[3..-2] || []).collect do |line|
- ids << line.split('|')[1].strip()
- end
- return ids
- end
-
- def self.get_glance_image_attr(id, attr)
- (auth_glance('image-show', id).split("\n") || []).collect do |line|
- if line =~ /^#{attr}:/
- return line.split(': ')[1..-1]
- end
- end
- end
-
- def self.get_glance_image_attrs(id)
- attrs = {}
- (auth_glance('image-show', id).split("\n")[3..-2] || []).collect do |line|
- attrs[line.split('|')[1].strip()] = line.split('|')[2].strip()
- end
- return attrs
- end
-
- def parse_table(table)
- # parse the table into an array of maps with a simplistic state machine
- found_header = false
- parsed_header = false
- keys = nil
- results = []
- table.split("\n").collect do |line|
- # look for the header
- if not found_header
- if line =~ /^\+[-|+]+\+$/
- found_header = true
- nil
- end
- # look for the key names in the table header
- elsif not parsed_header
- if line =~ /^(\|\s*[:alpha:]\s*)|$/
- keys = line.split('|').map(&:strip)
- parsed_header = true
- end
- # parse the values in the rest of the table
- elsif line =~ /^|.*|$/
- values = line.split('|').map(&:strip)
- result = Hash[keys.zip values]
- results << result
- end
- end
- results
- end
-
- # Remove warning from the output. This is a temporary hack until
- # things will be refactored to use the REST API
- def self.remove_warnings(results)
- found_header = false
- in_warning = false
- results.split("\n").collect do |line|
- unless found_header
- if line =~ /^\+[-\+]+\+$/ # Matches upper and lower box borders
- in_warning = false
- found_header = true
- line
- elsif line =~ /^WARNING/ or line =~ /UserWarning/ or in_warning
- # warnings can be multi line, we have to skip all of them
- in_warning = true
- nil
- else
- line
- end
- else
- line
- end
- end.compact.join("\n")
- end
-end