foreman_discovery 5.0.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)