foreman_discovery 5.0.2 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/discovered_hosts_controller.rb +4 -7
  3. data/app/controllers/api/v2/discovery_rules_controller.rb +1 -0
  4. data/app/controllers/api/v2/fact_values_controller_extensions.rb +11 -0
  5. data/app/controllers/concerns/foreman/controller/discovered_extensions.rb +6 -3
  6. data/app/controllers/discovered_hosts_controller.rb +46 -11
  7. data/app/controllers/discovery_rules_controller.rb +1 -1
  8. data/app/helpers/discovered_hosts_helper.rb +33 -16
  9. data/app/models/concerns/discovery_taxonomy_extensions.rb +7 -0
  10. data/app/models/concerns/fact_value_extensions.rb +8 -0
  11. data/app/models/discovery_rule.rb +4 -6
  12. data/app/models/host/discovered.rb +29 -10
  13. data/app/models/host/managed_extensions.rb +2 -10
  14. data/app/models/setting/discovered.rb +22 -28
  15. data/app/services/foreman_discovery/host_converter.rb +19 -10
  16. data/app/views/api/v2/discovered_hosts/main.json.rabl +1 -1
  17. data/app/views/dashboard/_discovery_widget_host.html.erb +1 -1
  18. data/app/views/discovered_hosts/_discovered_host.html.erb +1 -1
  19. data/app/views/discovered_hosts/_discovered_hosts_list.html.erb +32 -1
  20. data/app/views/discovered_hosts/index.html.erb +2 -2
  21. data/app/views/discovered_hosts/show.html.erb +5 -5
  22. data/app/views/discovered_mailer/_discovered_host.html.erb +1 -1
  23. data/app/views/discovered_mailer/discovered_summary.text.erb +2 -2
  24. data/app/views/discovery_rules/_form.html.erb +2 -19
  25. data/app/views/discovery_rules/_template_inline.erb +10 -0
  26. data/app/views/discovery_rules/index.html.erb +1 -1
  27. data/app/views/foreman_discovery/debian_kexec.erb +34 -0
  28. data/app/views/foreman_discovery/redhat_kexec.erb +5 -4
  29. data/config/routes.rb +4 -0
  30. data/db/migrate/20141223142759_fill_discovery_attribute_sets_for_existing_hosts.rb +15 -1
  31. data/db/migrate/20160719124942_add_missing_view_permissions.rb +18 -0
  32. data/db/seeds.d/50_discovery_templates.rb +15 -13
  33. data/lib/discovery.rake +1 -0
  34. data/lib/foreman_discovery/engine.rb +24 -10
  35. data/lib/foreman_discovery/version.rb +1 -1
  36. data/locale/ca/LC_MESSAGES/foreman_discovery.mo +0 -0
  37. data/locale/ca/foreman_discovery.edit.po +274 -136
  38. data/locale/ca/foreman_discovery.po +396 -328
  39. data/locale/de/LC_MESSAGES/foreman_discovery.mo +0 -0
  40. data/locale/de/foreman_discovery.edit.po +309 -171
  41. data/locale/de/foreman_discovery.po +419 -361
  42. data/locale/en/LC_MESSAGES/foreman_discovery.mo +0 -0
  43. data/locale/en/foreman_discovery.edit.po +881 -0
  44. data/locale/en/foreman_discovery.po +665 -0
  45. data/locale/en_GB/LC_MESSAGES/foreman_discovery.mo +0 -0
  46. data/locale/en_GB/foreman_discovery.edit.po +279 -141
  47. data/locale/en_GB/foreman_discovery.po +446 -391
  48. data/locale/es/LC_MESSAGES/foreman_discovery.mo +0 -0
  49. data/locale/es/foreman_discovery.edit.po +277 -139
  50. data/locale/es/foreman_discovery.po +415 -362
  51. data/locale/foreman_discovery.pot +241 -135
  52. data/locale/fr/LC_MESSAGES/foreman_discovery.mo +0 -0
  53. data/locale/fr/foreman_discovery.edit.po +289 -151
  54. data/locale/fr/foreman_discovery.po +439 -411
  55. data/locale/gl/LC_MESSAGES/foreman_discovery.mo +0 -0
  56. data/locale/gl/foreman_discovery.edit.po +266 -128
  57. data/locale/gl/foreman_discovery.po +320 -246
  58. data/locale/it/LC_MESSAGES/foreman_discovery.mo +0 -0
  59. data/locale/it/foreman_discovery.edit.po +277 -139
  60. data/locale/it/foreman_discovery.po +407 -352
  61. data/locale/ja/LC_MESSAGES/foreman_discovery.mo +0 -0
  62. data/locale/ja/foreman_discovery.edit.po +279 -141
  63. data/locale/ja/foreman_discovery.po +411 -339
  64. data/locale/ko/LC_MESSAGES/foreman_discovery.mo +0 -0
  65. data/locale/ko/foreman_discovery.edit.po +277 -139
  66. data/locale/ko/foreman_discovery.po +411 -339
  67. data/locale/pt_BR/LC_MESSAGES/foreman_discovery.mo +0 -0
  68. data/locale/pt_BR/foreman_discovery.edit.po +282 -144
  69. data/locale/pt_BR/foreman_discovery.po +430 -394
  70. data/locale/ru/LC_MESSAGES/foreman_discovery.mo +0 -0
  71. data/locale/ru/foreman_discovery.edit.po +371 -232
  72. data/locale/ru/foreman_discovery.po +448 -385
  73. data/locale/sv_SE/LC_MESSAGES/foreman_discovery.mo +0 -0
  74. data/locale/sv_SE/foreman_discovery.edit.po +270 -132
  75. data/locale/sv_SE/foreman_discovery.po +336 -260
  76. data/locale/zh_CN/LC_MESSAGES/foreman_discovery.mo +0 -0
  77. data/locale/zh_CN/foreman_discovery.edit.po +279 -141
  78. data/locale/zh_CN/foreman_discovery.po +412 -336
  79. data/locale/zh_TW/LC_MESSAGES/foreman_discovery.mo +0 -0
  80. data/locale/zh_TW/foreman_discovery.edit.po +279 -141
  81. data/locale/zh_TW/foreman_discovery.po +412 -338
  82. data/test/functional/api/v2/discovered_hosts_controller_test.rb +30 -22
  83. data/test/functional/api/v2/discovery_rules_controller_test.rb +7 -0
  84. data/test/functional/api/v2/fact_value_extensions_test.rb +37 -0
  85. data/test/functional/discovered_hosts_controller_test.rb +89 -16
  86. data/test/functional/discovery_rules_controller_test.rb +1 -1
  87. data/test/test_helper_discovery.rb +1 -1
  88. data/test/unit/discovered_extensions_test.rb +65 -21
  89. data/test/unit/discovery_attribute_set_test.rb +4 -4
  90. data/test/unit/discovery_taxonomy_extensions_test.rb +31 -0
  91. data/test/unit/host_discovered_test.rb +110 -14
  92. metadata +121 -110
  93. data/app/helpers/concerns/foreman_discovery/settings_helper_extensions.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a15855ae2fea53392d85bbf74e58ad95a03e2f31
4
- data.tar.gz: 4618507b72076897b1c03405964c7a544fa1a199
3
+ metadata.gz: 50f5e89c539ec3eb3bee287fc9251f4e0dad65f9
4
+ data.tar.gz: ccad5c9dcb424f30bd2802aaec3489b55aba7e71
5
5
  SHA512:
6
- metadata.gz: 87adf7fa08550375f25e021ed9fe6749acf5d4ef09aad6370b9630e34ac5066cd9fb0009a7a0cbae071da765da542f30e6ea13e641195f42130adacd9edffffa
7
- data.tar.gz: e03789da0d07c002a7098816e5b02875d55fdf7019cfcdfbab0076b13d2b9fa3b9feefbf657b92d539ec2690a49064bda090d6bac0c3e504fbf69666c7eaa62c
6
+ metadata.gz: 110b9578fc4bcf83d47e11254cbcd2c157268f2ba17c4aae6a9a21a47beeb68511b460f55d4427cbd88d7137d92dac1922589c2d4b20e48182799103e746f95c
7
+ data.tar.gz: c10cd4e42f0ac2c5d5a7eaa2b600a471a7f641e2d8a86fe3433201659813bba3f312a219f8efed4159697f0bbfd94ad39bd5c5d79f23fe95e43cdd738f796b11
@@ -94,13 +94,10 @@ module Api
94
94
 
95
95
  def facts
96
96
  state = true
97
- @discovered_host, state = Host::Discovered.import_host_and_facts(params[:facts])
98
- if Setting['discovery_auto']
99
- if state && rule = find_discovery_rule(@discovered_host)
100
- state = perform_auto_provision(@discovered_host, rule)
101
- else
102
- Rails.logger.warn "Discovered facts import unsuccessful, skipping auto provisioning"
103
- end
97
+ @discovered_host = Host::Discovered.import_host(params[:facts])
98
+ Rails.logger.warn "Discovered facts import unsuccessful, skipping auto provisioning" unless @discovered_host
99
+ if Setting['discovery_auto'] && @discovered_host && rule = find_discovery_rule(@discovered_host)
100
+ state = perform_auto_provision(@discovered_host, rule)
104
101
  end
105
102
  process_response state
106
103
  rescue Exception => e
@@ -35,6 +35,7 @@ module Api
35
35
  param :max_count, Integer, :desc => N_("enables to limit maximum amount of provisioned hosts per rule")
36
36
  param :priority, Integer, :desc => N_("puts the rules in order, low numbers go first. Must be greater then zero")
37
37
  param :enabled, :bool, :desc => N_("flag is used for temporary shutdown of rules")
38
+ param_group :taxonomies, ::Api::V2::BaseController
38
39
  end
39
40
  end
40
41
 
@@ -0,0 +1,11 @@
1
+ module Api
2
+ module V2
3
+ module FactValuesControllerExtensions
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ api :GET, "/discovered_hosts/:discovered_host_id/facts/", N_("List all fact values of a given discovered host")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -5,8 +5,8 @@ module Foreman::Controller::DiscoveredExtensions
5
5
  def find_discovery_rule host
6
6
  raise(::Foreman::Exception.new(N_("Unable to find a discovery rule, no host provided (check permissions)"))) if host.nil?
7
7
  Rails.logger.debug "Finding auto discovery rule for host #{host.name} (#{host.id})"
8
- # for each discovery rule ordered by priority
9
- DiscoveryRule.where(:enabled => true).order(:priority).each do |rule|
8
+ # rule with *lower* priority wins (older wins for same priority)
9
+ DiscoveryRule.where(:enabled => true).reorder(:priority, :created_at).each do |rule|
10
10
  max = rule.max_count
11
11
  usage = rule.hosts.size
12
12
  Rails.logger.debug "Found rule #{rule.name} (#{rule.id}) [#{usage}/#{max}]"
@@ -54,8 +54,11 @@ module Foreman::Controller::DiscoveredExtensions
54
54
  host.name = host.render_template(rule.hostname) unless rule.hostname.empty?
55
55
  # fallback to the original if template did not expand
56
56
  host.name = original_name if host.name.empty?
57
+ # explicitly set all inheritable attributes from hostgroup
58
+ host.attributes = host.apply_inherited_attributes(hostgroup_id: rule.hostgroup_id)
59
+ host.set_hostgroup_defaults
57
60
  # save! does not work here
58
- host.save
61
+ host.save ? host : false
59
62
  end
60
63
 
61
64
  def perform_reboot_all hosts = Host::Discovered.all
@@ -38,7 +38,7 @@ class DiscoveredHostsController < ::ApplicationController
38
38
  get_interfaces
39
39
  @host.facts_hash.each do |key, value|
40
40
  value = number_to_human_size(value) if /size$/.match(key)
41
- assign_fact_to_category(key, value) unless @interfaces.any? {|interface| key.include? interface[:identifier]}
41
+ assign_fact_to_category(key, value)
42
42
  end
43
43
  add_custom_facts
44
44
  end
@@ -50,20 +50,37 @@ class DiscoveredHostsController < ::ApplicationController
50
50
 
51
51
  def edit
52
52
  @host = ::ForemanDiscovery::HostConverter.to_managed(@host, true, false) unless @host.nil?
53
- render :template => 'hosts/edit'
53
+ @host.attributes = @host.apply_inherited_attributes(params[:host]) unless params[:host].empty?
54
+ @host.set_hostgroup_defaults
55
+ setup_host_class_variables(@host)
56
+ @override_taxonomy = true
57
+ if params[:quick_submit]
58
+ perform_update(@host, _('Successfully provisioned %s') % @host.name)
59
+ else
60
+ render :template => 'hosts/edit'
61
+ end
54
62
  end
55
63
 
56
64
  def update
57
65
  @host = ::ForemanDiscovery::HostConverter.to_managed(@host)
58
66
  forward_url_options
67
+ @host.attributes = params[:host]
68
+
69
+ perform_update(@host)
70
+ end
71
+
72
+ def perform_update(host, success_message = nil)
59
73
  Taxonomy.no_taxonomy_scope do
60
- if @host.update_attributes(params[:host])
61
- process_success :success_redirect => host_path(@host), :redirect_xhr => request.xhr?
74
+ ::ForemanDiscovery::HostConverter.set_build_clean_facts(host)
75
+ if host.save
76
+ success_options = { :success_redirect => host_path(host), :redirect_xhr => request.xhr? }
77
+ success_options[:success_msg] = success_message if success_message
78
+ process_success success_options
62
79
  else
63
80
  taxonomy_scope
64
81
  load_vars_for_ajax
65
82
  offer_to_overwrite_conflicts
66
- process_error :object => @host, :render => 'hosts/edit'
83
+ process_error :object => host, :render => 'hosts/edit'
67
84
  end
68
85
  end
69
86
  end
@@ -184,11 +201,23 @@ class DiscoveredHostsController < ::ApplicationController
184
201
 
185
202
  private
186
203
 
204
+ def setup_host_class_variables(host)
205
+ if host.hostgroup
206
+ @architecture = host.hostgroup.architecture
207
+ @operatingsystem = host.hostgroup.operatingsystem
208
+ @environment = host.hostgroup.environment
209
+ @domain = host.hostgroup.domain
210
+ @subnet = host.hostgroup.subnet
211
+ @compute_profile = host.hostgroup.compute_profile
212
+ @realm = host.hostgroup.realm
213
+ end
214
+ end
215
+
187
216
  def init_regex_and_categories
188
217
  hightlights = Setting[:discovery_facts_highlights].empty? ? /^(productname|memorysize|manufacturer|architecture|macaddress$|processorcount|physicalprocessorcount|discovery_subnet|discovery_boot|ipaddress$)/ : Regexp.new(Setting[:discovery_facts_highlights])
189
218
  storage = Setting[:discovery_facts_storage].empty? ? /^blockdevice/ : Regexp.new(Setting[:discovery_facts_storage])
190
219
  hardware = Setting[:discovery_facts_hardware].empty? ? /^(hardw|manufacturer|memo|process)/ : Regexp.new(Setting[:discovery_facts__hardware])
191
- network = Setting[:discovery_facts_network].empty? ? /^(ipaddress|interfaces|dhcp|fqdn|hostname|link|mtu|net|macaddress|wol|port|speed)/ : Regexp.new(Setting[:discovery_facts_network])
220
+ network = Setting[:discovery_facts_network].empty? ? /^(interfaces|dhcp|fqdn|hostname)/ : Regexp.new(Setting[:discovery_facts_network])
192
221
  software = Setting[:discovery_facts_software].empty? ? /^(bios|os|discovery)/ : Regexp.new(Setting[:discovery_facts_software])
193
222
  ipmi = Setting[:discovery_facts_ipmi].empty? ? /^ipmi/ : Regexp.new(Setting[:discovery_facts_ipmi])
194
223
  @regex_array = [hightlights, storage, hardware, network, software, ipmi, false]
@@ -196,7 +225,11 @@ class DiscoveredHostsController < ::ApplicationController
196
225
  @categories_names = [N_("Highlights"), N_("Storage"), N_("Hardware"), N_("Network"), N_("Software"), N_("IPMI"), N_("Miscellaneous")]
197
226
  end
198
227
 
199
- def assign_fact_to_category(key, value )
228
+ def assign_fact_to_category(key, value)
229
+ if @interfaces.any? {|interface| key.include? interface[:identifier]}
230
+ @categories[3][key] = value
231
+ return
232
+ end
200
233
  @regex_array.each_with_index do |regex, index|
201
234
  if !regex
202
235
  @categories[index][key] = value
@@ -249,10 +282,12 @@ class DiscoveredHostsController < ::ApplicationController
249
282
  end
250
283
 
251
284
  def find_by_name(*includes)
252
- params[:id].downcase! if params[:id].present?
253
- @host = includes.empty? ? resource_base.find_by_id(params[:id]) : resource_base.includes(includes).find_by_id(params[:id])
254
- @host ||= includes.empty? ? resource_base.find_by_name(params[:id]) : resource_base.includes(includes).find_by_name(params[:id])
255
- return false unless @host
285
+ not_found and return false if (id = params[:id]).blank?
286
+ id.downcase!
287
+ @host = includes.empty? ? resource_base.find_by_id(id) : resource_base.includes(includes).find_by_id(id)
288
+ @host ||= includes.empty? ? resource_base.find_by_name(id) : resource_base.includes(includes).find_by_name(id)
289
+ not_found and return(false) unless @host
290
+ @host
256
291
  end
257
292
 
258
293
  def find_by_name_incl_subnet
@@ -5,7 +5,7 @@ class DiscoveryRulesController < ApplicationController
5
5
  before_filter :find_resource, :only => [:edit, :update, :destroy, :enable, :disable, :auto_provision]
6
6
 
7
7
  def index
8
- base = resource_base.search_for(params[:search], :order => (params[:order] || 'priority ASC'))
8
+ base = resource_base.search_for(params[:search], :order => (params[:order]))
9
9
  @discovery_rules = base.paginate(:page => params[:page]).includes(:hostgroup)
10
10
  end
11
11
 
@@ -1,5 +1,4 @@
1
1
  module DiscoveredHostsHelper
2
-
3
2
  def attach_flags(interface)
4
3
  flags = ""
5
4
  flags += "flag-primary " if interface[:primary]
@@ -12,28 +11,22 @@ module DiscoveredHostsHelper
12
11
  end
13
12
 
14
13
  def discovered_hosts_title_actions(host)
15
- actions = [[_('Provision'), hash_for_edit_discovered_host_path(:id => host)]]
16
- actions << [_('Auto Provision'), hash_for_auto_provision_discovered_host_path(:id => host), :method => :post]
17
- actions << [_('Refresh facts') ,hash_for_refresh_facts_discovered_host_path(:id => host)]
18
- actions << [_('Reboot') ,hash_for_reboot_discovered_host_path(:id => host), :method => :put]
14
+ actions = [[_('Provision'), hash_for_edit_discovered_host_path(:id => host).merge(:auth_object => host, :permission => :provision_discovered_hosts)]]
15
+ actions << [_('Auto Provision'), hash_for_auto_provision_discovered_host_path(:id => host).merge(:auth_object => host, :permission => :auto_provision_discovered_hosts), :method => :post]
16
+ actions << [_('Refresh facts') ,hash_for_refresh_facts_discovered_host_path(:id => host).merge(:auth_object => host, :permission => :edit_discovered_hosts)]
17
+ actions << [_('Reboot') ,hash_for_reboot_discovered_host_path(:id => host).merge(:auth_object => host, :permission => :edit_discovered_hosts), :method => :put]
19
18
  title_actions(
20
19
  button_group(
21
- link_to(_("Back"), :back)
22
- ),
23
- select_action_button( _("Select Action"), {},
24
- actions.map do |action|
25
- method = action[2] if action.size > 1
26
- link_to(action[0] , action[1], method)
27
- end.flatten
20
+ link_to(_("Back"), :back, :class => "btn btn-default")
28
21
  ),
22
+ select_action_button( _("Select Action"), {}, actions.map { |action| display_link_if_authorized(action[0] , action[1], action[2] || {}) }.flatten ),
29
23
  button_group(
30
- link_to(_("Expand All"),"#",:class => "btn ",:onclick => "$('.glyphicon-plus-sign').toggleClass('glyphicon glyphicon-minus-sign glyphicon glyphicon-plus-sign');
24
+ link_to(_("Expand All"),"#",:class => "btn btn-default",:onclick => "$('.glyphicon-plus-sign').toggleClass('glyphicon glyphicon-minus-sign glyphicon glyphicon-plus-sign');
31
25
  $('.facts-panel').addClass('collapse in').height('auto');"
32
26
  )
33
27
  ),
34
28
  button_group(
35
- link_to(_("Delete"), hash_for_discovered_host_path(:id => host),
36
- :class => "btn btn-danger", :confirm => _('Are you sure?'), :method => :delete)
29
+ display_delete_if_authorized(hash_for_discovered_host_path(:id => host).merge(:auth_object => host, :permission => :destroy_discovered_hosts), :class => "btn btn-danger", :data => { :confirm => _('Delete %s?') % host.name })
37
30
  )
38
31
  )
39
32
  end
@@ -68,7 +61,7 @@ module DiscoveredHostsHelper
68
61
  status_glyph = 'glyphicon-plus-sign'
69
62
  status_message = _('New in the last 24 hours')
70
63
  status_color = '#89A54E'
71
- elsif host.last_report < 7.days.ago
64
+ elsif host.last_report.present? && host.last_report < 7.days.ago
72
65
  status_glyph = 'glyphicon-exclamation-sign'
73
66
  status_message = _('Not reported in more than 7 days')
74
67
  status_color = '#AA4643'
@@ -81,4 +74,28 @@ module DiscoveredHostsHelper
81
74
  "<span class='glyphicon #{status_glyph}' style='color: #{status_color}'
82
75
  title='#{status_message}'/>".html_safe
83
76
  end
77
+
78
+ def host_taxonomy_select(f, taxonomy)
79
+ # Add hidden field with taxonomy value to be updated by the form on submit
80
+ tax_html = super
81
+ tax_id = "#{taxonomy.to_s.downcase}_id"
82
+ selected_taxonomy = params[:host][tax_id] if params[:host]
83
+ if @override_taxonomy && selected_taxonomy
84
+ hidden_tax = f.hidden_field tax_id.to_sym, :value => selected_taxonomy
85
+ tax_html += hidden_tax
86
+ end
87
+ tax_html
88
+ end
89
+
90
+ def provision_button(host, authorization_options)
91
+ return '' unless authorized_for(authorization_options)
92
+
93
+ button_tag(
94
+ _('Provision'),
95
+ :type => :button,
96
+ :class => 'btn btn-sm btn-default',
97
+ :data => {
98
+ :toggle => 'modal',
99
+ :target => "#fixedPropertiesSelector-#{host.id}"})
100
+ end
84
101
  end
@@ -0,0 +1,7 @@
1
+ module DiscoveryTaxonomyExtensions
2
+ extend ActiveSupport::Concern
3
+ included do
4
+ has_many :discovered_hosts, :class_name => 'Host::Discovered'
5
+ before_destroy ActiveRecord::Base::EnsureNotUsedBy.new(:discovered_hosts)
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module FactValueExtensions
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ belongs_to :discovered_host, :class_name => "Host::Discovered", :foreign_key => :host_id
6
+ scoped_search :in => :discovered_host, :on => :id, :complete_enabled => false, :only_explicit => true, :rename => :discovered_host
7
+ end
8
+ end
@@ -28,13 +28,11 @@ class DiscoveryRule < ActiveRecord::Base
28
28
  scoped_search :on => :enabled
29
29
  scoped_search :in => :hostgroup, :on => :name, :complete_value => true, :rename => :hostgroup
30
30
 
31
- # with proc support, default_scope can no longer be chained
32
- # include all default scoping here
33
31
  default_scope lambda {
34
- with_taxonomy_scope do
35
- order("discovery_rules.name")
36
- end
37
- }
32
+ with_taxonomy_scope do
33
+ order('discovery_rules.priority, discovery_rules.created_at')
34
+ end
35
+ }
38
36
 
39
37
  def default_int_attributes
40
38
  self.max_count ||= 0
@@ -1,5 +1,6 @@
1
1
  class Host::Discovered < ::Host::Base
2
2
  include ScopedSearchExtensions
3
+ include Foreman::Renderer
3
4
 
4
5
  attr_accessible :discovery_rule_id
5
6
 
@@ -30,7 +31,7 @@ class Host::Discovered < ::Host::Base
30
31
  where(taxonomy_conditions).order("hosts.created_at DESC")
31
32
  }
32
33
 
33
- def self.import_host_and_facts facts
34
+ def self.import_host facts
34
35
  raise(::Foreman::Exception.new(N_("Invalid facts, must be a Hash"))) unless facts.is_a?(Hash)
35
36
 
36
37
  # filter facts
@@ -47,15 +48,21 @@ class Host::Discovered < ::Host::Base
47
48
  hostname = normalize_string_for_hostname("#{hostname_prefix}#{name_fact}")
48
49
  Rails.logger.warn "Hostname does not start with an alphabetical character" unless hostname.downcase.match /^[a-z]/
49
50
 
50
- # create new host record
51
- host = ::Host::Discovered.includes(:interfaces).find_by_name hostname
52
- host ||= Host.new :name => hostname, :type => "Host::Discovered"
51
+ # find existing or create new host record
52
+ bootif_mac = FacterUtils::bootif_mac(facts).try(:downcase)
53
+ hosts = ::Nic::Managed.where(:mac => bootif_mac, :primary => true)
54
+ if hosts.size == 0
55
+ host = Host.new(:name => hostname, :type => "Host::Discovered")
56
+ else
57
+ Rails.logger.warn "Multiple discovered hosts found with MAC address #{name_fact}, choosing one" if hosts.size > 1
58
+ host = hosts.first.host
59
+ end
53
60
  host.type = "Host::Discovered"
54
61
 
55
62
  # and save (interfaces are created via puppet parser extension)
56
63
  host.save(:validate => false) if host.new_record?
57
- state = host.import_facts(facts)
58
- return host, state
64
+ raise ::Foreman::Exception.new(N_("Facts could not be imported")) unless host.import_facts(facts)
65
+ host
59
66
  end
60
67
 
61
68
  def import_facts facts
@@ -75,7 +82,7 @@ class Host::Discovered < ::Host::Base
75
82
  super
76
83
  end
77
84
 
78
- def populate_fields_from_facts(facts = self.facts_hash, ignored_type)
85
+ def populate_fields_from_facts(facts = self.facts_hash, ignored_type = nil)
79
86
  # detect interfaces and primary interface using extensions
80
87
  parser = super(facts, :foreman_discovery)
81
88
 
@@ -92,13 +99,13 @@ class Host::Discovered < ::Host::Base
92
99
  self.primary_interface.subnet = subnet
93
100
  # set location and organization
94
101
  if SETTINGS[:locations_enabled]
95
- self.location = Location.find_by_name(Setting[:discovery_location]) ||
102
+ self.location = Location.find_by_title(Setting[:discovery_location]) ||
96
103
  subnet.try(:locations).try(:first) ||
97
104
  Location.first
98
105
  Rails.logger.info "Assigned location: #{self.location}"
99
106
  end
100
107
  if SETTINGS[:organizations_enabled]
101
- self.organization = Organization.find_by_name(Setting[:discovery_organization]) ||
108
+ self.organization = Organization.find_by_title(Setting[:discovery_organization]) ||
102
109
  subnet.try(:organizations).try(:first) ||
103
110
  Organization.first
104
111
  Rails.logger.info "Assigned organization: #{self.organization}"
@@ -108,6 +115,17 @@ class Host::Discovered < ::Host::Base
108
115
  end
109
116
  self.discovery_attribute_set = DiscoveryAttributeSet.where(:host_id => id).first_or_create
110
117
  self.discovery_attribute_set.update_attributes(import_from_facts)
118
+ # lock the host into discovery via PXE, if feature is enabled in settings
119
+ if Setting::Discovered.discovery_lock? && self.subnet.tftp?
120
+ begin
121
+ @host = self
122
+ Rails.logger.info "Locking discovered host #{self.mac} in subnet #{subnet}"
123
+ template = unattended_render(::ProvisioningTemplate.find_by_name(Setting['discovery_lock_template']).template)
124
+ subnet.tftp_proxy.set mac, :pxeconfig => template
125
+ rescue ::Foreman::Exception => e
126
+ ::Foreman::Logging.exception("Could not set tftp_proxy from proxy", e)
127
+ end
128
+ end
111
129
  self.save!
112
130
  parser
113
131
  end
@@ -144,7 +162,8 @@ class Host::Discovered < ::Host::Base
144
162
 
145
163
  def refresh_facts
146
164
  facts = ::ForemanDiscovery::NodeAPI::Inventory.new(:url => proxy_url).facter
147
- self.class.import_host_and_facts facts
165
+ self.class.import_host facts
166
+ import_facts facts
148
167
  rescue Exception => e
149
168
  raise _("Could not get facts from proxy %{url}: %{error}") % {:url => proxy_url, :error => e}
150
169
  end
@@ -41,20 +41,12 @@ module Host::ManagedExtensions
41
41
  # no reboot on orchestration rollback
42
42
  end
43
43
 
44
- def boot_url pxe_file
45
- raise ::Foreman::Exception.new(N_("Operating system not set for host/hostgroup")) unless operatingsystem
46
- base = operatingsystem.medium_uri(self)
47
- raise ::Foreman::Exception.new(N_("Medium not set for host/hostgroup")) unless base
48
- path = operatingsystem.url_for_boot(pxe_file)
49
- operatingsystem.medium_vars_to_uri("#{base}/#{path}", architecture.name, operatingsystem).to_s
50
- end
51
-
52
44
  def setKexec
53
45
  template = provisioning_template(:kind => 'kexec')
54
46
  raise ::Foreman::Exception.new(N_("Kexec template not associated with operating system")) unless template
55
47
  @host = self
56
- @kernel = boot_url(:kernel)
57
- @initrd = boot_url(:initrd)
48
+ # the following two attributes are overwritten by TFTP in preview mode (kept for compatibility)
49
+ @kernel, @initrd = operatingsystem.boot_files_uri(@host.medium, @host.architecture)
58
50
  json = unattended_render(template)
59
51
  old.becomes(Host::Discovered).kexec json
60
52
  true
@@ -16,50 +16,40 @@ class Setting::Discovered < ::Setting
16
16
 
17
17
  Setting.transaction do
18
18
  [
19
- self.set('discovery_fact', N_("Fact name to use for primary interface detection"), "discovery_bootif"),
20
- self.set('discovery_hostname', N_("List of facts to use for the hostname (separated by comma, first wins)"), "discovery_bootif"),
21
- self.set('discovery_auto', N_("Automatically provision newly discovered hosts, according to the provisioning rules"), false),
22
- self.set('discovery_reboot', N_("Automatically reboot discovered host during provisioning"), true),
23
- ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
24
- end
25
-
26
- Setting.transaction do
27
- [
28
- self.set('discovery_prefix', N_("The default prefix to use for the host name, must start with a letter"), "mac"),
29
- ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
30
- end
31
-
32
- Setting.transaction do
33
- [
34
- self.set('discovery_fact_column', N_("Extra facter columns to show in host lists (separate by comma)"), ""),
19
+ self.set('discovery_fact', N_("Fact name to use for primary interface detection"), "discovery_bootif", N_("Interface fact")),
20
+ self.set('discovery_clean_facts', N_("Clean all reported facts during provisioning (except discovery facts)"), false, N_("Clean all facts")),
21
+ self.set('discovery_hostname', N_("List of facts to use for the hostname (separated by comma, first wins)"), "discovery_bootif", N_("Hostname facts")),
22
+ self.set('discovery_auto', N_("Automatically provision newly discovered hosts, according to the provisioning rules"), false, N_("Auto provisioning")),
23
+ self.set('discovery_reboot', N_("Automatically reboot or kexec discovered host during provisioning"), true, N_("Reboot")),
24
+ self.set('discovery_prefix', N_("The default prefix to use for the host name, must start with a letter"), "mac", N_("Hostname prefix")),
25
+ self.set('discovery_fact_column', N_("Extra facter columns to show in host lists (separate by comma)"), "", N_("Fact columns")),
26
+ self.set('discovery_facts_highlights', N_("Regex to organize facts for highlights section - e.g. ^(abc|cde)$"), "", N_("Highlighted facts")),
27
+ self.set('discovery_facts_storage', N_("Regex to organize facts for storage section"), "", N_("Storage facts")),
28
+ self.set('discovery_facts_software', N_("Regex to organize facts for software section"), "", N_("Software facts")),
29
+ self.set('discovery_facts_hardware', N_("Regex to organize facts for hardware section"), "", N_("Hardware facts")),
30
+ self.set('discovery_facts_network', N_("Regex to organize facts for network section"), "", N_("Network facts")),
31
+ self.set('discovery_facts_ipmi', N_("Regex to organize facts for ipmi section"), "", N_("IPMI facts")),
32
+ self.set('discovery_lock', N_("Automatically generate PXE configuration to pin a newly discovered host to discovery"), false, N_("Lock PXE")),
33
+ self.set('discovery_lock_template', N_("PXE template to be used when pinning a host to discovery"), 'pxelinux_discovery', N_("Locked template name"),nil,{ :collection => Proc.new {Hash[ProvisioningTemplate.all.map{|template| [template[:name], template[:name]]}]} }),
35
34
  ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
36
35
  end
37
36
 
38
37
  if SETTINGS[:locations_enabled]
39
38
  Setting.transaction do
40
39
  [
41
- self.set('discovery_location', N_("The default location to place discovered hosts in"), ""),
40
+ self.set('discovery_location', N_("The default location to place discovered hosts in"), "", N_("Discovery location"), nil, { :collection => Proc.new {Hash[Location.all.map{|loc| [loc[:title], loc[:title]]}]} }),
42
41
  ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
43
42
  end
44
43
  end
44
+
45
45
  if SETTINGS[:organizations_enabled]
46
46
  Setting.transaction do
47
47
  [
48
- self.set('discovery_organization', N_("The default organization to place discovered hosts in"), "" ),
48
+ self.set('discovery_organization', N_("The default organization to place discovered hosts in"), "", N_("Discovery organization"), nil, { :collection => Proc.new {Hash[Organization.all.map{|org| [org[:title], org[:title]]}]} }),
49
49
  ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
50
50
  end
51
51
  end
52
52
 
53
- Setting.transaction do
54
- [
55
- self.set('discovery_facts_highlights', N_("Regex to organize facts for highlights section - e.g. ^(abc|cde)$"), ""),
56
- self.set('discovery_facts_storage', N_("Regex to organize facts for storage section"), ""),
57
- self.set('discovery_facts_software', N_("Regex to organize facts for software section"), ""),
58
- self.set('discovery_facts_hardware', N_("Regex to organize facts for hardware section"), ""),
59
- self.set('discovery_facts_network', N_("Regex to organize facts for network section"), ""),
60
- self.set('discovery_facts_ipmi', N_("Regex to organize facts for ipmi section"), ""),
61
- ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
62
- end
63
53
  true
64
54
  end
65
55
 
@@ -72,6 +62,10 @@ class Setting::Discovered < ::Setting
72
62
  from_array Setting['discovery_hostname']
73
63
  end
74
64
 
65
+ def self.discovery_lock?
66
+ Foreman::Cast.to_bool(Setting['discovery_lock']) && !Setting['discovery_lock_template'].blank? && ProvisioningTemplate.exists?(:name => Setting['discovery_lock_template'])
67
+ end
68
+
75
69
  def self.from_array(setting)
76
70
  return [] unless setting.present?
77
71
  setting.to_s.split(",").map(&:strip)