Revision c83e29ac
Added by Lukas Zapletal about 10 years ago
app/assets/javascripts/i18n.js | ||
---|---|---|
// Add normal gettext aliases with gettext_i18n_rails_js to enable extraction
|
||
// when SETTINGS[:mark_translated] is enabled, wrap all strings
|
||
if (typeof(I18N_MARK) != 'undefined' && I18N_MARK) {
|
||
window.__ = function() { return 'X' + i18n.gettext.apply(i18n, arguments) + 'X' };
|
||
window.n__ = function() { return 'X' + i18n.ngettext.apply(i18n, arguments) + 'X' };
|
||
window.__ = function() { return '\u00BB' + i18n.gettext.apply(i18n, arguments) + '\u00AB' };
|
||
window.n__ = function() { return '\u00BB' + i18n.ngettext.apply(i18n, arguments) + '\u00AB' };
|
||
}
|
||
});
|
app/models/concerns/orchestration.rb | ||
---|---|---|
|
||
private
|
||
|
||
def proxy_error e
|
||
e.respond_to?(:message) ? e.message : e
|
||
end
|
||
# Handles the actual queue
|
||
# takes care for running the tasks in order
|
||
# if any of them fail, it rollbacks all completed tasks
|
||
... | ... | |
rescue Net::LeaseConflict => e
|
||
task.status = "failed"
|
||
failure _("DHCP has a lease at %s") % e, e.backtrace
|
||
rescue RestClient::Exception => e
|
||
task.status = "failed"
|
||
failure _("%{task} task failed with the following error: %{e}") % { :task => task.name, :e => proxy_error(e) }, e.backtrace
|
||
rescue => e
|
||
task.status = "failed"
|
||
failure _("%{task} task failed with the following error: %{e}") % { :task => task.name, :e => e }, e.backtrace
|
app/models/concerns/orchestration/dhcp.rb | ||
---|---|---|
# if that failed, trying to guess out tftp next server based on the smart proxy hostname
|
||
bs ||= URI.parse(subnet.tftp.url).host
|
||
# now convert it into an ip address (see http://theforeman.org/issues/show/1381)
|
||
return to_ip_address(bs) if bs.present?
|
||
ip = to_ip_address(bs) if bs.present?
|
||
return ip unless ip.nil?
|
||
|
||
failure _("Unable to determine the host's boot server. The DHCP smart proxy failed to provide this information and this subnet is not provided with TFTP services.")
|
||
rescue => e
|
app/models/concerns/orchestration/puppetca.rb | ||
---|---|---|
def delCertificate
|
||
logger.info "Remove puppet certificate for #{name}"
|
||
puppetca.del_certificate certname
|
||
rescue => e
|
||
failure _("Failed to remove %{name}'s puppet certificate: %{e}") % { :name => name, :e => proxy_error(e) }
|
||
end
|
||
|
||
# Empty method for rollbacks - maybe in the future we would support creating the certificates directly
|
||
... | ... | |
def setAutosign
|
||
logger.info "Adding autosign entry for #{name}"
|
||
puppetca.set_autosign certname
|
||
rescue => e
|
||
failure _("Failed to add %{name} to autosign file: %{e}") % { :name => name, :e => proxy_error(e) }
|
||
end
|
||
|
||
# Removes the host's name from the autosign.conf file
|
||
def delAutosign
|
||
logger.info "Delete the autosign entry for #{name}"
|
||
puppetca.del_autosign certname
|
||
rescue => e
|
||
failure _("Failed to remove %{self} from the autosign file: %{e}") % { :self => self, :e => proxy_error(e) }
|
||
end
|
||
|
||
private
|
app/models/concerns/orchestration/tftp.rb | ||
---|---|---|
def setTFTP
|
||
logger.info "Add the TFTP configuration for #{name}"
|
||
tftp.set mac, :pxeconfig => generate_pxe_template
|
||
rescue => e
|
||
failure _("Failed to set TFTP: %s") % proxy_error(e)
|
||
end
|
||
|
||
# Removes the host from the forward and reverse TFTP zones
|
||
... | ... | |
def delTFTP
|
||
logger.info "Delete the TFTP configuration for #{name}"
|
||
tftp.delete mac
|
||
rescue => e
|
||
failure _("Failed to delete TFTP: %s") % proxy_error(e)
|
||
end
|
||
|
||
def setTFTPBootFiles
|
||
... | ... | |
end
|
||
failure _("Failed to fetch boot files") unless valid
|
||
valid
|
||
rescue => e
|
||
failure _("Failed to fetch boot files: %s") % proxy_error(e)
|
||
end
|
||
|
||
#empty method for rollbacks
|
app/models/host/managed.rb | ||
---|---|---|
# otherwise, use normal systems dns settings to resolv
|
||
def to_ip_address name_or_ip
|
||
return name_or_ip if name_or_ip =~ Net::Validations::IP_REGEXP
|
||
return dns_ptr_record.dns_lookup(name_or_ip).ip if dns_ptr_record
|
||
if dns_ptr_record
|
||
lookup = dns_ptr_record.dns_lookup(name_or_ip)
|
||
return lookup.ip unless lookup.nil?
|
||
end
|
||
# fall back to normal dns resolution
|
||
domain.resolver.getaddress(name_or_ip).to_s
|
||
rescue => e
|
||
logger.warn "Unable to find IP address for '#{name_or_ip}': #{e}"
|
||
raise ::Foreman::WrappedException.new(e, N_("Unable to find IP address for '%s'"), name_or_ip)
|
||
end
|
||
|
||
def set_default_user
|
app/services/foreman/wrapped_exception.rb | ||
---|---|---|
module Foreman
|
||
|
||
class WrappedException < ::Foreman::Exception
|
||
def initialize exception, message, *params
|
||
def initialize wrapped_exception, message, *params
|
||
super(message, *params)
|
||
@exception = exception
|
||
@wrapped_exception = wrapped_exception
|
||
end
|
||
|
||
def wrapped_exception
|
||
@exception
|
||
@wrapped_exception
|
||
end
|
||
|
||
def message
|
||
if @exception.nil?
|
||
if @wrapped_exception.nil?
|
||
wrapped = ""
|
||
super
|
||
else
|
||
wrapped = " (#{@exception.class.name} - #{@exception.message})"
|
||
cls = @wrapped_exception.class.name
|
||
msg = @wrapped_exception.message.try(:truncate, 90)
|
||
super + " ([#{cls}]: #{msg})"
|
||
end
|
||
"#{code}: #{@message}#{wrapped}"
|
||
end
|
||
end
|
||
|
lib/foreman/exception.rb | ||
---|---|---|
@params = params
|
||
end
|
||
|
||
# Error code is made up first 8 characters of base64 (RFC 4648) encoded MD5
|
||
# sum of concatenated classname and message
|
||
def self.calculate_error_code classname, message
|
||
class_hash = Zlib::crc32(classname) % 100
|
||
return 'ERF00-0000' if classname.nil? or message.nil?
|
||
basename = classname.split(':').last
|
||
class_hash = Zlib::crc32(basename) % 100
|
||
msg_hash = Zlib::crc32(message) % 10000
|
||
sprintf "ERF%02d-%04d", class_hash, msg_hash
|
||
end
|
||
... | ... | |
if Kernel.respond_to? :_
|
||
translated_msg = _(@message) % @params
|
||
else
|
||
translated_msg = @message
|
||
# use plain ruby interpolation
|
||
translated_msg = @message % @params
|
||
end
|
||
"#{code}: #{translated_msg}"
|
||
"#{code} [#{self.class.name}]: #{translated_msg}"
|
||
end
|
||
|
||
alias :to_s :message
|
||
def to_s
|
||
message
|
||
end
|
||
end
|
||
|
||
class FingerprintException < Exception
|
lib/foreman/gettext/debug.rb | ||
---|---|---|
# include this module to see translations in the UI
|
||
module Foreman::Gettext::Debug
|
||
|
||
DL = "\u00BB".encode("UTF-8") rescue '>'
|
||
DR = "\u00AB".encode("UTF-8") rescue '<'
|
||
|
||
# slightly modified copy of fast_gettext D_* method
|
||
def _(key)
|
||
FastGettext.translation_repositories.each_key do |domain|
|
||
result = FastGettext::TranslationMultidomain.d_(domain, key) {nil}
|
||
return "X#{result}X" unless result.nil?
|
||
return DL + result + DR unless result.nil?
|
||
end
|
||
'X' + key + 'X'
|
||
DL + key + DR
|
||
end
|
||
|
||
# slightly modified copy of fast_gettext D_* method
|
||
def n_(*keys)
|
||
FastGettext.translation_repositories.each_key do |domain|
|
||
result = FastGettext::TranslationMultidomain.dn_(domain, *keys) {nil}
|
||
return "X#{result}X" unless result.nil?
|
||
return DL + result + DR unless result.nil?
|
||
end
|
||
'X' + keys[-3].split(keys[-2]||FastGettext::NAMESPACE_SEPARATOR).last + 'X'
|
||
DL + keys[-3].split(keys[-2]||FastGettext::NAMESPACE_SEPARATOR).last + DR
|
||
end
|
||
|
||
# slightly modified copy of fast_gettext D_* method
|
||
def s_(key, separator=nil)
|
||
FastGettext.translation_repositories.each_key do |domain|
|
||
result = FastGettext::TranslationMultidomain.ds_(domain, key, separator) {nil}
|
||
return "X#{result}X" unless result.nil?
|
||
return DL + result + DR unless result.nil?
|
||
end
|
||
'X' + key.split(separator||FastGettext::NAMESPACE_SEPARATOR).last + 'X'
|
||
DL + key.split(separator||FastGettext::NAMESPACE_SEPARATOR).last + DR
|
||
end
|
||
|
||
# slightly modified copy of fast_gettext D_* method
|
||
def ns_(*keys)
|
||
FastGettext.translation_repositories.each_key do |domain|
|
||
result = FastGettext::TranslationMultidomain.dns_(domain, *keys) {nil}
|
||
return "X#{result}X" unless result.nil?
|
||
return DL + result + DR unless result.nil?
|
||
end
|
||
'X' + keys[-2].split(FastGettext::NAMESPACE_SEPARATOR).last + 'X'
|
||
DL + keys[-2].split(FastGettext::NAMESPACE_SEPARATOR).last + DR
|
||
end
|
||
end
|
lib/foreman/gettext/support.rb | ||
---|---|---|
else
|
||
FastGettext.default_available_locales = Dir.glob(locale_search_path).collect {|f| locale_search_re.match(f)[1] }
|
||
end
|
||
rescue Exception => e
|
||
rescue => e
|
||
Rails.logger.warn "Unable to set available locales for domain #{locale_domain}: #{e}"
|
||
FastGettext.default_available_locales = ['en']
|
||
end
|
lib/proxy_api/bmc.rb | ||
---|---|---|
# gets a list of supported providers
|
||
def providers
|
||
parse get("providers")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get BMC providers"))
|
||
end
|
||
|
||
# gets a list of supported providers installed on the proxy
|
||
def providers_installed
|
||
parse get("providers/installed")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get installed BMC providers"))
|
||
end
|
||
|
||
# Perform a boot operation on the bmc device
|
||
... | ... | |
else
|
||
raise NoMethodError
|
||
end
|
||
rescue NoMethodError => e
|
||
raise e
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to perform boot BMC operation"))
|
||
end
|
||
|
||
# Perform a power operation on the bmc device
|
||
... | ... | |
else
|
||
raise NoMethodError
|
||
end
|
||
rescue NoMethodError => e
|
||
raise e
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to perform power BMC operation"))
|
||
end
|
||
|
||
# perform an identify operation on the bmc device
|
||
... | ... | |
else
|
||
raise NoMethodError
|
||
end
|
||
|
||
rescue NoMethodError => e
|
||
raise e
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to perform identify BMC operation"))
|
||
end
|
||
|
||
# perform a lan get operation on the bmc device
|
||
... | ... | |
else
|
||
raise NoMethodError
|
||
end
|
||
rescue NoMethodError => e
|
||
raise e
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to perform lan BMC operation"))
|
||
end
|
||
|
||
private
|
lib/proxy_api/dhcp.rb | ||
---|---|---|
# Example [{"network":"192.168.11.0","netmask":"255.255.255.0"},{"network":"192.168.122.0","netmask":"255.255.255.0"}]
|
||
def subnets
|
||
parse get
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to retrieve DHCP subnets"))
|
||
end
|
||
|
||
def subnet subnet
|
||
parse get(subnet)
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to retrieve DHCP subnet"))
|
||
end
|
||
|
||
def unused_ip subnet, mac = nil
|
||
... | ... | |
params = ""
|
||
end
|
||
parse get("#{subnet.network}/unused_ip#{params}")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to retrieve unused IP"))
|
||
end
|
||
|
||
# Retrieves a DHCP entry
|
||
... | ... | |
end
|
||
rescue RestClient::ResourceNotFound
|
||
nil
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to retrieve DHCP entry for %s"), mac)
|
||
end
|
||
|
||
# Sets a DHCP entry
|
||
... | ... | |
raise "Must define a subnet" if subnet.empty?
|
||
raise "Must provide arguments" unless args.is_a?(Hash)
|
||
parse(post(args, subnet.to_s))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to set DHCP entry"))
|
||
end
|
||
|
||
# Deletes a DHCP entry
|
||
... | ... | |
rescue RestClient::ResourceNotFound
|
||
# entry doesn't exists anyway
|
||
return true
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to delete DHCP entry for %s"), mac)
|
||
end
|
||
end
|
||
end
|
lib/proxy_api/dns.rb | ||
---|---|---|
# Returns : Boolean status
|
||
def set args
|
||
parse post(args, "")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to set DNS entry"))
|
||
end
|
||
|
||
# Deletes a DNS entry
|
||
... | ... | |
rescue RestClient::ResourceNotFound
|
||
# entry doesn't exists anyway
|
||
return true
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to delete DNS entry"))
|
||
end
|
||
end
|
||
end
|
lib/proxy_api/features.rb | ||
---|---|---|
|
||
def features
|
||
parse get
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to detect features"))
|
||
end
|
||
end
|
||
end
|
lib/proxy_api/proxy_exception.rb | ||
---|---|---|
module ProxyAPI
|
||
|
||
class ProxyException < ::Foreman::WrappedException
|
||
|
||
attr_reader :url
|
||
|
||
def initialize url, exception, message, *params
|
||
super(exception, message, *params)
|
||
@url = url
|
||
end
|
||
|
||
def message
|
||
super + ' ' + _('for proxy') + ' ' + url
|
||
end
|
||
end
|
||
|
||
end
|
lib/proxy_api/puppet.rb | ||
---|---|---|
|
||
def environments
|
||
parse(get "environments")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get environments from Puppet"))
|
||
end
|
||
|
||
def environment env
|
||
parse(get "environments/#{env}")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get environment from Puppet"))
|
||
end
|
||
|
||
def classes env
|
||
... | ... | |
Hash[pcs.map { |k| [k.keys.first, Foreman::ImporterPuppetclass.new(k.values.first)] }]
|
||
rescue RestClient::ResourceNotFound
|
||
[]
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get classes from Puppet for %s"), env)
|
||
end
|
||
|
||
def run hosts
|
||
parse(post({:nodes => hosts}, "run"))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to execute Puppet run"))
|
||
end
|
||
end
|
||
end
|
lib/proxy_api/puppetca.rb | ||
---|---|---|
|
||
def autosign
|
||
parse(get "autosign")
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get PuppetCA autosign"))
|
||
end
|
||
|
||
def set_autosign certname
|
||
parse(post("", "autosign/#{certname}"))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to set PuppetCA autosign for %s"), certname)
|
||
end
|
||
|
||
def del_autosign certname
|
||
... | ... | |
rescue RestClient::ResourceNotFound
|
||
# entry doesn't exists anyway
|
||
true
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to delete PuppetCA autosign for %s"), certname)
|
||
end
|
||
|
||
def sign_certificate certname
|
||
parse(post("", certname))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to sign PuppetCA certificate for %s"), certname)
|
||
end
|
||
|
||
def del_certificate certname
|
||
... | ... | |
rescue RestClient::ResourceNotFound
|
||
# entry doesn't exists anyway
|
||
true
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to delete PuppetCA certificate for %s"), certname)
|
||
end
|
||
|
||
def all
|
||
parse(get)
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to get PuppetCA certificates"))
|
||
end
|
||
end
|
||
end
|
lib/proxy_api/tftp.rb | ||
---|---|---|
# Returns : Boolean status
|
||
def set mac, args
|
||
parse(post(args, "#{@variant}/#{mac}"))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to set TFTP boot entry for %s"), mac)
|
||
end
|
||
|
||
# Deletes a TFTP boot entry
|
||
... | ... | |
# Returns : Boolean status
|
||
def delete mac
|
||
parse(super("#{@variant}/#{mac}"))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to delete TFTP boot entry for %s"), mac)
|
||
end
|
||
|
||
# Requests that the proxy download the bootfile from the media's source
|
||
... | ... | |
# Returns : Boolean status
|
||
def fetch_boot_file args
|
||
parse(post(args, "fetch_boot_file"))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to fetch TFTP boot file"))
|
||
end
|
||
|
||
# returns the TFTP boot server for this proxy
|
||
... | ... | |
false
|
||
rescue RestClient::ResourceNotFound
|
||
nil
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to detect TFTP boot server"))
|
||
end
|
||
|
||
# Create a default pxe menu
|
||
... | ... | |
# Returns : Boolean status
|
||
def create_default args
|
||
parse(post(args, "create_default"))
|
||
rescue => e
|
||
raise ProxyException.new(url, e, N_("Unable to create default TFTP boot menu"))
|
||
end
|
||
|
||
end
|
lib/tasks/exception.rake | ||
---|---|---|
task :codes => :environment do
|
||
wiki = defined? ENV['WIKI']
|
||
exceptions = [
|
||
::Foreman::Exception,
|
||
::Foreman::WrappedException,
|
||
'Foreman::Exception',
|
||
'WrappedException',
|
||
'ProxyException',
|
||
]
|
||
result = {}
|
||
regexp = /raise.*:?:?(#{exceptions.join('|')})(\.new)?\(?N_\(?(["'])([^\3]+?)\3\)?\)?/
|
||
regexp = /raise.*(#{exceptions.join('|')})(\.new)?.*N_\(?(["'])([^\3]+?)\3\)?\)?/
|
||
Dir['app/**/*rb', 'lib/**/*rb'].each do |path|
|
||
File.open(path) do |f|
|
||
f.grep( /#{regexp}/ ) do |line|
|
||
... | ... | |
|
||
result.keys.sort.each do |k|
|
||
v = result[k]
|
||
puts "#{k} #{v}"
|
||
puts " * [[#{k}]] - #{v}"
|
||
end
|
||
end
|
||
|
test/functional/api/v2/hosts_controller_test.rb | ||
---|---|---|
facts = fact_json['facts']
|
||
post :facts, {:name => hostname, :facts => facts, :type => "Host::Invalid"}, set_session_user
|
||
assert_response :unprocessable_entity
|
||
assert_equal JSON.parse(response.body)['message'], 'ERF51-2640: A problem occurred when detecting host type: uninitialized constant Host::Invalid'
|
||
assert JSON.parse(response.body)['message'] =~ /ERF42-2640/
|
||
end
|
||
|
||
test "when the imported host failed to save, :unprocessable_entity is returned" do
|
Also available in: Unified diff
fixes #1966 - improved UI errors for proxy