foreman_discovery 16.3.6 → 17.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/discovered_hosts_controller.rb +1 -0
- data/app/controllers/discovered_hosts_controller.rb +24 -35
- data/app/controllers/discovery_rules_controller.rb +12 -1
- data/app/helpers/discovered_hosts_helper.rb +3 -4
- data/app/helpers/discovery_rules_helper.rb +1 -0
- data/app/models/discovery_rule.rb +10 -5
- data/app/services/foreman_discovery/fact_to_category_resolver.rb +106 -0
- data/app/services/foreman_discovery/ui_notifications/failed_discovery.rb +34 -0
- data/app/services/foreman_discovery/ui_notifications/new_host.rb +2 -1
- data/app/views/discovered_hosts/_discovered_hosts_list.html.erb +44 -40
- data/app/views/discovered_hosts/welcome.html.erb +1 -1
- data/app/views/discovery_rules/clone.erb +3 -0
- data/app/views/discovery_rules/index.html.erb +4 -0
- data/app/views/discovery_rules/welcome.html.erb +15 -0
- data/config/routes.rb +2 -0
- data/db/seeds.d/80_discovery_ui_notification.rb +11 -5
- data/lib/foreman_discovery/engine.rb +3 -7
- data/lib/foreman_discovery/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ca/foreman_discovery.edit.po +44 -40
- data/locale/ca/foreman_discovery.po +36 -9
- data/locale/de/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/de/foreman_discovery.edit.po +42 -38
- data/locale/de/foreman_discovery.po +45 -18
- data/locale/en/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en/foreman_discovery.edit.po +37 -29
- data/locale/en/foreman_discovery.po +31 -4
- data/locale/en_GB/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en_GB/foreman_discovery.edit.po +39 -35
- data/locale/en_GB/foreman_discovery.po +36 -9
- data/locale/es/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/es/foreman_discovery.edit.po +42 -38
- data/locale/es/foreman_discovery.po +70 -41
- data/locale/foreman_discovery.pot +142 -97
- data/locale/fr/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/fr/foreman_discovery.edit.po +88 -84
- data/locale/fr/foreman_discovery.po +76 -49
- data/locale/gl/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/gl/foreman_discovery.edit.po +42 -38
- data/locale/gl/foreman_discovery.po +32 -5
- data/locale/it/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/it/foreman_discovery.edit.po +42 -38
- data/locale/it/foreman_discovery.po +44 -17
- data/locale/ja/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ja/foreman_discovery.edit.po +74 -70
- data/locale/ja/foreman_discovery.po +79 -54
- data/locale/ko/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ko/foreman_discovery.edit.po +42 -38
- data/locale/ko/foreman_discovery.po +43 -16
- data/locale/pt_BR/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/pt_BR/foreman_discovery.edit.po +42 -38
- data/locale/pt_BR/foreman_discovery.po +69 -39
- data/locale/ru/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ru/foreman_discovery.edit.po +46 -42
- data/locale/ru/foreman_discovery.po +43 -16
- data/locale/sv_SE/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/sv_SE/foreman_discovery.edit.po +42 -38
- data/locale/sv_SE/foreman_discovery.po +34 -7
- data/locale/zh_CN/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_CN/foreman_discovery.edit.po +90 -86
- data/locale/zh_CN/foreman_discovery.po +114 -90
- data/locale/zh_TW/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_TW/foreman_discovery.edit.po +42 -38
- data/locale/zh_TW/foreman_discovery.po +43 -16
- data/package.json +6 -6
- data/test/functional/api/v2/discovered_hosts_controller_test.rb +9 -0
- data/test/functional/discovery_rules_controller_test.rb +6 -1
- data/test/integration/discovered_hosts_test.rb +53 -5
- data/test/test_helper_discovery.rb +5 -0
- data/test/unit/discovery_rule_test.rb +24 -2
- data/test/unit/fact_to_category_resolver_test.rb +41 -0
- data/test/unit/ui_notifications/destroy_host_test.rb +2 -9
- data/test/unit/ui_notifications/new_host_test.rb +3 -3
- data/webpack/__mocks__/foremanReact/common/I18n.js +3 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +1 -0
- data/webpack/__mocks__/foremanReact/common/index.js +5 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/DefaultEmptyState.js +69 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/EmptyStatePattern.js +77 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/EmptyStatePropTypes.js +29 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState/index.js +5 -0
- data/webpack/index.js +9 -8
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/EmptyState.js +7 -7
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/__test__/EmptyState.test.js +12 -0
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/__test__/__snapshots__/EmptyState.test.js.snap +16 -0
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/index.js +1 -1
- data/webpack/src/ForemanDiscovery/DiscoveredHosts/index.js +3 -3
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/EmptyState/EmptyState.js +34 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/EmptyState/index.js +1 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/__test__/EmptyState.test.js +19 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/Components/__test__/__snapshots__/EmptyState.test.js.snap +22 -0
- data/webpack/src/ForemanDiscovery/DiscoveryRules/index.js +6 -0
- data/webpack/src/reducers.js +0 -2
- metadata +31 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d8d075f8a3a3048021cb510037e84ce925e805d3cb915a2d739bd188a99d08f
|
4
|
+
data.tar.gz: 2851a8920c2e7da750c92104e26ce286cd723aab684e8f3e08d452ea458f5d3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ddc4a716ab29ec7cf78c052e8238184962c97d528592f171e074664e2542e603ffc9d3bce44bf255c787c82cc3df82faf6a7d61a98d9046fca544a957589e4a
|
7
|
+
data.tar.gz: 3d72b88c68fb69a56e1f691c1df6a93bc42b5c2157f79ee0ad9293ea85b4aa15510ebd130e1d8464fdb6593d6aed01e0adee3c688f6d698a8194cca8f281158a
|
@@ -122,6 +122,7 @@ module Api
|
|
122
122
|
end
|
123
123
|
process_response state
|
124
124
|
rescue Exception => e
|
125
|
+
ForemanDiscovery::UINotifications::FailedDiscovery.new(e).deliver!
|
125
126
|
Foreman::Logging.exception("Host discovery failed, facts: #{facts}", e)
|
126
127
|
render :json => {'message'=>e.to_s}, :status => :unprocessable_entity
|
127
128
|
end
|
@@ -9,6 +9,7 @@ class DiscoveredHostsController < ::ApplicationController
|
|
9
9
|
before_action :find_by_name_incl_subnet, :only => [:show]
|
10
10
|
before_action :find_multiple, :only => [:multiple_destroy, :submit_multiple_destroy, :multiple_reboot, :submit_multiple_reboot, :multiple_auto_provision, :submit_multiple_auto_provision]
|
11
11
|
before_action :taxonomy_scope, :only => [:edit]
|
12
|
+
before_action :check_for_subnet, :only => [:reboot, :auto_provision, :submit_multiple_reboot, :submit_multiple_auto_provision]
|
12
13
|
|
13
14
|
around_action :skip_bullet, :only => [:edit]
|
14
15
|
|
@@ -38,14 +39,10 @@ class DiscoveredHostsController < ::ApplicationController
|
|
38
39
|
@range = nil
|
39
40
|
# summary report text
|
40
41
|
@report_summary = nil
|
41
|
-
|
42
|
-
@
|
43
|
-
|
44
|
-
@
|
45
|
-
value = number_to_human_size(value) if /size$/.match(key)
|
46
|
-
assign_fact_to_category(key, value)
|
47
|
-
end
|
48
|
-
add_custom_facts
|
42
|
+
resolver = ForemanDiscovery::FactToCategoryResolver.new(@host)
|
43
|
+
@categories_names = ForemanDiscovery::FactToCategoryResolver::CATEGORIES_NAMES
|
44
|
+
@categories = resolver.categories
|
45
|
+
@interfaces = resolver.interfaces
|
49
46
|
end
|
50
47
|
|
51
48
|
def destroy
|
@@ -214,33 +211,6 @@ class DiscoveredHostsController < ::ApplicationController
|
|
214
211
|
end
|
215
212
|
end
|
216
213
|
|
217
|
-
def init_regex_and_categories
|
218
|
-
hightlights = Setting[:discovery_facts_highlights].empty? ? /^(productname|memorysize|manufacturer|architecture|macaddress$|processorcount|physicalprocessorcount|discovery_subnet|discovery_boot|ipaddress$)/ : Regexp.new(Setting[:discovery_facts_highlights])
|
219
|
-
storage = Setting[:discovery_facts_storage].empty? ? /^blockdevice/ : Regexp.new(Setting[:discovery_facts_storage])
|
220
|
-
hardware = Setting[:discovery_facts_hardware].empty? ? /^(hardw|manufacturer|memo|process)/ : Regexp.new(Setting[:discovery_facts__hardware])
|
221
|
-
network = Setting[:discovery_facts_network].empty? ? /^(interfaces|dhcp|fqdn|hostname)/ : Regexp.new(Setting[:discovery_facts_network])
|
222
|
-
software = Setting[:discovery_facts_software].empty? ? /^(bios|os|discovery)/ : Regexp.new(Setting[:discovery_facts_software])
|
223
|
-
ipmi = Setting[:discovery_facts_ipmi].empty? ? /^ipmi/ : Regexp.new(Setting[:discovery_facts_ipmi])
|
224
|
-
@regex_array = [hightlights, storage, hardware, network, software, ipmi, false]
|
225
|
-
@categories = Array.new(7) { Hash.new }
|
226
|
-
@categories_names = [N_("Highlights"), N_("Storage"), N_("Hardware"), N_("Network"), N_("Software"), N_("IPMI"), N_("Miscellaneous")]
|
227
|
-
end
|
228
|
-
|
229
|
-
def assign_fact_to_category(key, value)
|
230
|
-
if @interfaces.any? {|interface| key.include? interface[:identifier]}
|
231
|
-
@categories[3][key] = value
|
232
|
-
return
|
233
|
-
end
|
234
|
-
@regex_array.each_with_index do |regex, index|
|
235
|
-
if !regex
|
236
|
-
@categories[index][key] = value
|
237
|
-
elsif regex.match key
|
238
|
-
@categories[index][key] = value
|
239
|
-
break
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
214
|
def resource_base
|
245
215
|
@resource_base ||= ::Host::Discovered.authorized(current_permission, ::Host::Discovered)
|
246
216
|
end
|
@@ -292,6 +262,21 @@ class DiscoveredHostsController < ::ApplicationController
|
|
292
262
|
@host
|
293
263
|
end
|
294
264
|
|
265
|
+
def check_for_subnet
|
266
|
+
hosts_without_subnet = []
|
267
|
+
case params[:action]
|
268
|
+
when 'reboot', 'auto_provision'
|
269
|
+
if @host.subnet.nil?
|
270
|
+
process_warning :warning_msg => _("Discovered host reported from unknown subnet, communication will not be proxied.")
|
271
|
+
end
|
272
|
+
when 'submit_multiple_reboot', 'submit_multiple_auto_provision'
|
273
|
+
hosts_without_subnet = @hosts.limit(3).select { |host| host.subnet.nil? }.pluck(:name)
|
274
|
+
if hosts_without_subnet.present?
|
275
|
+
process_warning :warning_msg => _("Discovered hosts reported from unknown subnet are %s, communication will not be proxied.") % hosts_without_subnet.join(', ')
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
295
280
|
def find_by_name_incl_subnet
|
296
281
|
find_by_name({:interfaces => :subnet})
|
297
282
|
end
|
@@ -347,4 +332,8 @@ class DiscoveredHostsController < ::ApplicationController
|
|
347
332
|
assign_fact_to_category("discovery_subnet", discovery_subnet)
|
348
333
|
end
|
349
334
|
end
|
335
|
+
|
336
|
+
def process_warning(hash = {})
|
337
|
+
warning hash[:warning_msg]
|
338
|
+
end
|
350
339
|
end
|
@@ -4,7 +4,11 @@ class DiscoveryRulesController < ApplicationController
|
|
4
4
|
|
5
5
|
include Foreman::Controller::Parameters::DiscoveryRule
|
6
6
|
|
7
|
-
before_action :find_resource, :only => [:edit, :update, :destroy, :enable, :disable, :auto_provision]
|
7
|
+
before_action :find_resource, :only => [:edit, :update, :destroy, :enable, :disable, :auto_provision, :clone]
|
8
|
+
|
9
|
+
def model_of_controller
|
10
|
+
DiscoveryRule
|
11
|
+
end
|
8
12
|
|
9
13
|
def index
|
10
14
|
base = resource_base.search_for(params[:search], :order => (params[:order]))
|
@@ -15,6 +19,11 @@ class DiscoveryRulesController < ApplicationController
|
|
15
19
|
@discovery_rule = DiscoveryRule.new(:priority => DiscoveryRule.suggest_priority)
|
16
20
|
end
|
17
21
|
|
22
|
+
def clone
|
23
|
+
@discovery_rule.deep_clone except: [:name, :priority], include: [:organizations, :locations]
|
24
|
+
@discovery_rule.priority = DiscoveryRule.suggest_priority
|
25
|
+
end
|
26
|
+
|
18
27
|
def create
|
19
28
|
@discovery_rule = DiscoveryRule.new(discovery_rule_params)
|
20
29
|
if @discovery_rule.save
|
@@ -55,6 +64,8 @@ class DiscoveryRulesController < ApplicationController
|
|
55
64
|
|
56
65
|
def action_permission
|
57
66
|
case params[:action]
|
67
|
+
when 'clone'
|
68
|
+
:create
|
58
69
|
when 'enable', 'disable'
|
59
70
|
:edit
|
60
71
|
else
|
@@ -7,7 +7,7 @@ module DiscoveredHostsHelper
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def disc_report_column(record)
|
10
|
-
record.last_report? ? (
|
10
|
+
record.last_report? ? date_time_relative(record.last_report.getlocal) : ""
|
11
11
|
end
|
12
12
|
|
13
13
|
def discovered_hosts_title_actions(host)
|
@@ -98,8 +98,7 @@ module DiscoveredHostsHelper
|
|
98
98
|
discovered_host_path(host)
|
99
99
|
end
|
100
100
|
|
101
|
-
def
|
102
|
-
|
103
|
-
"https://theforeman.org/plugins/foreman_discovery/#{doc_version}"
|
101
|
+
def discovery_doc_version
|
102
|
+
Foreman::Plugin.find(:foreman_discovery).version.scan(/\d+\.\d+/).first
|
104
103
|
end
|
105
104
|
end
|
@@ -30,6 +30,7 @@ module DiscoveryRulesHelper
|
|
30
30
|
else
|
31
31
|
actions << display_link_if_authorized(_('Enable'), hash_for_enable_discovery_rule_path(:id => rule).merge(:auth_object => rule, :authorizer => authorizer), :data => { :confirm => _("Enable rule '%s'?") % rule })
|
32
32
|
end
|
33
|
+
actions << display_link_if_authorized(_("Clone"), hash_for_clone_discovery_rule_path(id: rule).merge(auth_object: rule, authorizer: authorizer))
|
33
34
|
actions << display_delete_if_authorized(hash_for_discovery_rule_path(:id => rule).merge(:auth_object => rule, :authorizer => authorizer), :data => { :confirm => _("Delete rule '%s'?") % rule })
|
34
35
|
end
|
35
36
|
end
|
@@ -17,7 +17,6 @@ class DiscoveryRule < ApplicationRecord
|
|
17
17
|
validates :max_count, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0, :less_than => 2**31 }
|
18
18
|
validates :priority, :presence => true, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0, :less_than => 2**31 }
|
19
19
|
validates_lengths_from_database
|
20
|
-
validates_uniqueness_of :priority
|
21
20
|
before_validation :default_int_attributes
|
22
21
|
before_validation :enforce_taxonomy
|
23
22
|
|
@@ -41,19 +40,25 @@ class DiscoveryRule < ApplicationRecord
|
|
41
40
|
self.priority ||= 0
|
42
41
|
end
|
43
42
|
|
44
|
-
def self.suggest_priority
|
45
|
-
|
43
|
+
def self.suggest_priority(organization = Organization.current)
|
44
|
+
discovery_rules = DiscoveryRule.unscoped
|
45
|
+
return (discovery_rules.maximum(:priority).to_i + STEP) if organization.nil?
|
46
|
+
discovery_rule_ids = TaxableTaxonomy.where(
|
47
|
+
taxable_type: 'DiscoveryRule',
|
48
|
+
taxonomy_id: organization.id).pluck(:taxable_id)
|
49
|
+
discovery_rules = discovery_rules.where(id: discovery_rule_ids)
|
50
|
+
discovery_rules.maximum(:priority).to_i + STEP
|
46
51
|
end
|
47
52
|
|
48
53
|
def enforce_taxonomy
|
49
54
|
return if hostgroup.nil?
|
50
55
|
unless (ms = hostgroup.organizations - organizations).empty?
|
51
56
|
names = ms.collect(&:name).to_sentence
|
52
|
-
errors.add(:
|
57
|
+
errors.add(:base, n_("Host group organization %s must also be associated to the discovery rule", "Host group organizations %s must also be associated to the discovery rule", ms.size) % names)
|
53
58
|
end
|
54
59
|
unless (ms = hostgroup.locations - locations).empty?
|
55
60
|
names = ms.collect(&:name).to_sentence
|
56
|
-
errors.add(:
|
61
|
+
errors.add(:base, n_("Host group location %s must also be associated to the discovery rule", "Host group locations %s must also be associated to the discovery rule", ms.size) % names)
|
57
62
|
end
|
58
63
|
end
|
59
64
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module ForemanDiscovery
|
2
|
+
class FactToCategoryResolver
|
3
|
+
include ActionView::Helpers::NumberHelper
|
4
|
+
|
5
|
+
attr_reader :categories, :interfaces
|
6
|
+
|
7
|
+
CATEGORIES_NAMES = [N_("Highlights"),
|
8
|
+
N_("Storage"),
|
9
|
+
N_("Hardware"),
|
10
|
+
N_("Network"),
|
11
|
+
N_("Software"),
|
12
|
+
N_("IPMI"),
|
13
|
+
N_("Miscellaneous")].freeze
|
14
|
+
|
15
|
+
def initialize(host)
|
16
|
+
categories = %i[highlights storage hardware network software ipmi]
|
17
|
+
|
18
|
+
@regex_array = categories.map do |category|
|
19
|
+
settings_category = settings_discovery_fact_prefix(category)
|
20
|
+
if settings_category.empty?
|
21
|
+
send(category)
|
22
|
+
else
|
23
|
+
Regexp.new(settings_category)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@regex_array << false
|
28
|
+
|
29
|
+
@categories = []
|
30
|
+
|
31
|
+
@interfaces = host.interfaces.map do |interface|
|
32
|
+
{
|
33
|
+
identifier: interface["identifier"],
|
34
|
+
type: interface["type"],
|
35
|
+
mac: interface["mac"],
|
36
|
+
ip: interface["ip"] || "N/A",
|
37
|
+
primary: interface["primary"],
|
38
|
+
provision: interface["provision"],
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
assign_facts(host)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def assign_facts(host)
|
48
|
+
host.facts_hash.each do |key, value|
|
49
|
+
value = number_to_human_size(value) if /size$/.match(key)
|
50
|
+
assign_fact_to_category(key, value)
|
51
|
+
end
|
52
|
+
|
53
|
+
return if host.primary_interface.subnet.nil?
|
54
|
+
|
55
|
+
discovery_subnet = "#{host.primary_interface.subnet.name} (#{host.primary_interface.subnet.network})"
|
56
|
+
assign_fact_to_category("discovery_subnet", discovery_subnet)
|
57
|
+
end
|
58
|
+
|
59
|
+
def assign_fact_to_category(key, value)
|
60
|
+
if @interfaces.any? { |interface| key.include? interface[:identifier] }
|
61
|
+
@categories[3] = {} if @categories[3].nil?
|
62
|
+
@categories[3][key] = value
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
@regex_array.each_with_index do |regex, index|
|
67
|
+
@categories[index] = {} if @categories[index].nil?
|
68
|
+
if !regex
|
69
|
+
@categories[index][key] = value
|
70
|
+
elsif regex.match key
|
71
|
+
@categories[index][key] = value
|
72
|
+
break
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def highlights
|
78
|
+
/^(productname|memorysize|manufacturer|architecture|macaddress$|processorcount|physicalprocessorcount|discovery_subnet|discovery_boot|ipaddress$)/
|
79
|
+
end
|
80
|
+
|
81
|
+
def storage
|
82
|
+
/^blockdevice/
|
83
|
+
end
|
84
|
+
|
85
|
+
def hardware
|
86
|
+
/^(hardw|manufacturer|memo|process)/
|
87
|
+
end
|
88
|
+
|
89
|
+
def network
|
90
|
+
/^(interfaces|dhcp|fqdn|hostname)/
|
91
|
+
end
|
92
|
+
|
93
|
+
def software
|
94
|
+
/^(bios|os|discovery)/
|
95
|
+
end
|
96
|
+
|
97
|
+
def ipmi
|
98
|
+
/^ipmi/
|
99
|
+
end
|
100
|
+
|
101
|
+
def settings_discovery_fact_prefix(name)
|
102
|
+
Setting["discovery_facts_#{name}".to_sym]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ForemanDiscovery
|
3
|
+
module UINotifications
|
4
|
+
# Adds notification upon failed discovery
|
5
|
+
class FailedDiscovery < ::UINotifications::Base
|
6
|
+
def initialize(message)
|
7
|
+
@message = message
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def create
|
13
|
+
add_notification if update_notifications.zero?
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_notifications
|
17
|
+
blueprint.mass_update_expiry
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_notification
|
21
|
+
Notification.create!(
|
22
|
+
initiator: initiator,
|
23
|
+
audience: ::Notification::AUDIENCE_ADMIN,
|
24
|
+
message: _("One or more hosts with failed discovery due to error: #{@message}"),
|
25
|
+
notification_blueprint: blueprint,
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def blueprint
|
30
|
+
@blueprint ||= NotificationBlueprint.find_by(name: 'failed_discovery')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -8,7 +8,7 @@ module ForemanDiscovery
|
|
8
8
|
private
|
9
9
|
|
10
10
|
def create
|
11
|
-
add_notification
|
11
|
+
add_notification
|
12
12
|
end
|
13
13
|
|
14
14
|
def update_notifications
|
@@ -19,6 +19,7 @@ module ForemanDiscovery
|
|
19
19
|
Notification.create!(
|
20
20
|
initiator: initiator,
|
21
21
|
audience: ::Notification::AUDIENCE_SUBJECT,
|
22
|
+
message: _("Host %s has been dicovered") % subject.name,
|
22
23
|
subject: subject,
|
23
24
|
notification_blueprint: blueprint
|
24
25
|
)
|
@@ -1,47 +1,51 @@
|
|
1
1
|
<% title _('Discovered Hosts') %>
|
2
2
|
<table class="<%= table_css_classes('table-condensed') %>" >
|
3
|
-
<
|
4
|
-
<th class="ca"><%= check_box_tag "check_all", "", false, { :onclick => "tfm.hosts.table.toggleCheck()", :'check-title' => _("Select all items in this page"), :'uncheck-title'=> _("items selected. Uncheck to Clear") } %></th>
|
5
|
-
<th class=''><%= sort :name, :as => _('Name') %></th>
|
6
|
-
<th class="hidden-tablet hidden-xs"><%= sort :model, :as => _('Model') %></th>
|
7
|
-
<th class="hidden-tablet hidden-xs"><%= sort :ip, :as => _('IP Address') %></th>
|
8
|
-
<th class="hidden-tablet hidden-xs"><%= sort :cpu_count, :as => _('CPUs') %></th>
|
9
|
-
<th class="hidden-tablet hidden-xs"><%= sort :memory, :as => _('Memory') %></th>
|
10
|
-
<th class="hidden-tablet hidden-xs"><%= sort :disk_count, :as => _('Disk Count') %></th>
|
11
|
-
<th class="hidden-tablet hidden-xs"><%= sort :disks_size, :as => _('Disks Size') %></th>
|
12
|
-
<% Setting::Discovered.discovery_fact_column_array.each do |fact_column| %>
|
13
|
-
<th class="hidden-tablet hidden-xs"><%= fact_column.capitalize %></th>
|
14
|
-
<% end %>
|
15
|
-
<th class="hidden-tablet hidden-xs"><%= sort :location, :as => _('Location') %></th>
|
16
|
-
<th class="hidden-tablet hidden-xs"><%= sort :organization, :as => _('Organization') %></th>
|
17
|
-
<th class="hidden-tablet hidden-xs"><%= sort :subnet, :as => _("Subnet") %></th>
|
18
|
-
<th class="hidden-tablet hidden-xs"><%= sort :last_report, :as => _("Last Facts Upload") %></th>
|
19
|
-
<th class="hidden-tablet hidden-xs"><%= _("Actions") %></th>
|
20
|
-
</tr>
|
21
|
-
<% @hosts.each do |host| -%>
|
3
|
+
<thead>
|
22
4
|
<tr>
|
23
|
-
<
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
<
|
28
|
-
<
|
29
|
-
<
|
30
|
-
<
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
5
|
+
<th class="ca"><%= check_box_tag "check_all", "", false, { :onclick => "tfm.hosts.table.toggleCheck()", :'check-title' => _("Select all items in this page"), :'uncheck-title'=> _("items selected. Uncheck to Clear") } %></th>
|
6
|
+
<th class=''><%= sort :name, :as => _('Name') %></th>
|
7
|
+
<th class="hidden-tablet hidden-xs"><%= sort :model, :as => _('Model') %></th>
|
8
|
+
<th class="hidden-tablet hidden-xs"><%= sort :ip, :as => _('IP Address') %></th>
|
9
|
+
<th class="hidden-tablet hidden-xs"><%= sort :cpu_count, :as => _('CPUs') %></th>
|
10
|
+
<th class="hidden-tablet hidden-xs"><%= sort :memory, :as => _('Memory') %></th>
|
11
|
+
<th class="hidden-tablet hidden-xs"><%= sort :disk_count, :as => _('Disk Count') %></th>
|
12
|
+
<th class="hidden-tablet hidden-xs"><%= sort :disks_size, :as => _('Disks Size') %></th>
|
13
|
+
<% Setting::Discovered.discovery_fact_column_array.each do |fact_column| %>
|
14
|
+
<th class="hidden-tablet hidden-xs"><%= fact_column.capitalize %></th>
|
15
|
+
<% end %>
|
16
|
+
<th class="hidden-tablet hidden-xs"><%= sort :location, :as => _('Location') %></th>
|
17
|
+
<th class="hidden-tablet hidden-xs"><%= sort :organization, :as => _('Organization') %></th>
|
18
|
+
<th class="hidden-tablet hidden-xs"><%= sort :subnet, :as => _("Subnet") %></th>
|
19
|
+
<th class="hidden-tablet hidden-xs"><%= sort :last_report, :as => _("Last Facts Upload") %></th>
|
20
|
+
<th class="hidden-tablet hidden-xs"><%= _("Actions") %></th>
|
21
|
+
</tr>
|
22
|
+
</thead>
|
23
|
+
<tbody>
|
24
|
+
<% @hosts.each do |host| -%>
|
25
|
+
<tr>
|
26
|
+
<td class="ca">
|
27
|
+
<%= check_box_tag "host_ids[]", nil, false, :id => "host_ids_#{host.id}", :disabled => !authorized_for_edit_destroy?, :class => 'host_select_boxes', :onclick => 'tfm.hosts.table.hostChecked(this)' -%>
|
41
28
|
</td>
|
42
|
-
|
43
|
-
|
44
|
-
|
29
|
+
<%= render :partial => "discovered_host", :locals => {:host => host} %>
|
30
|
+
<td class="hidden-tablet hidden-xs"><%= host.location.try(:title) %></td>
|
31
|
+
<td class="hidden-tablet hidden-xs"><%= host.organization.try(:title) %></td>
|
32
|
+
<td class="hidden-tablet hidden-xs"><%= host.primary_interface.try(:subnet).try(:to_label) %></td>
|
33
|
+
<td class="hidden-tablet hidden-xs"><%= disc_report_column(host) %></td>
|
34
|
+
<td>
|
35
|
+
<!-- Modal -->
|
36
|
+
<%= render :partial => "discovered_host_modal", :locals => {:host => host} %>
|
37
|
+
</div>
|
38
|
+
<%= action_buttons(
|
39
|
+
provision_button(host, hash_for_edit_discovered_host_path(:id => host)),
|
40
|
+
display_link_if_authorized(_("Auto Provision"), hash_for_auto_provision_discovered_host_path(:id => host), :method => :post),
|
41
|
+
display_link_if_authorized(_("Refresh facts"), hash_for_refresh_facts_discovered_host_path(:id => host)),
|
42
|
+
display_link_if_authorized(_("Reboot"), hash_for_reboot_discovered_host_path(:id => host), :method => :put),
|
43
|
+
display_delete_if_authorized(hash_for_discovered_host_path(:id => host), :data => { :confirm => _("Delete %s?") % host.name }, :action => :destroy)) %>
|
44
|
+
</td>
|
45
|
+
</tr>
|
46
|
+
<% end -%>
|
47
|
+
</tbody>
|
48
|
+
</table>
|
45
49
|
|
46
50
|
<div id="confirmation-modal" class="modal fade">
|
47
51
|
<div class="modal-dialog">
|
@@ -11,5 +11,5 @@
|
|
11
11
|
<%= notifications %>
|
12
12
|
<div id="organization-id" data-id="<%= Organization.current.id if Organization.current %>" ></div>
|
13
13
|
<div id="user-id" data-id="<%= User.current.id if User.current %>" ></div>
|
14
|
-
<%= react_component('DiscoveredHosts', docUrl:
|
14
|
+
<%= react_component('DiscoveredHosts', docUrl: external_link_path(type: 'plugin_manual', name: 'foreman_discovery', version: discovery_doc_version)) %>
|
15
15
|
<% end %>
|
@@ -8,6 +8,8 @@
|
|
8
8
|
<th><%= sort :search, :as => s_("DiscoveryRule|Query") %></th>
|
9
9
|
<th><%= _("Host Group") %></th>
|
10
10
|
<th><%= _("Hosts/Limit") %></th>
|
11
|
+
<th><%= sort :location, :as => _('Location') %></th>
|
12
|
+
<th><%= sort :organization, :as => _('Organization') %></th>
|
11
13
|
<th><%= sort :enabled, :as => s_("DiscoveryRule|Enabled") %></th>
|
12
14
|
<th><%= _("Actions") %></th>
|
13
15
|
</tr>
|
@@ -18,6 +20,8 @@
|
|
18
20
|
<td><%= trunc_with_tooltip(rule.search) %></td>
|
19
21
|
<td><%= label_with_link(rule.hostgroup, 26, authorizer) %></td>
|
20
22
|
<td><%= rule.hosts.count %> / <%= rule.max_count %></td>
|
23
|
+
<td><%= rule.locations.find_by(title: Location.current.try(:title)).try(:title) || rule.locations.pluck(:title).join(",") %></td>
|
24
|
+
<td><%= rule.organizations.find_by(title: Organization.current.try(:title)).try(:title) || rule.organizations.pluck(:title).join(",") %></td>
|
21
25
|
<td><%= checked_icon rule.enabled %></td>
|
22
26
|
<td><%= action_buttons(*permitted_discovery_actions(rule)) %></td>
|
23
27
|
</tr>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% content_for(:javascripts) do %>
|
2
|
+
<%= webpacked_plugins_js_for :'foreman_discovery' %>
|
3
|
+
<% end %>
|
4
|
+
<% content_for(:stylesheets) do %>
|
5
|
+
<%= webpacked_plugins_css_for :'foreman_discovery' %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<% content_for(:title, _("Discovered Rules")) %>
|
9
|
+
|
10
|
+
<% content_for(:content) do %>
|
11
|
+
<%= notifications %>
|
12
|
+
<div id="organization-id" data-id="<%= Organization.current.id if Organization.current %>" ></div>
|
13
|
+
<div id="user-id" data-id="<%= User.current.id if User.current %>" ></div>
|
14
|
+
<%= react_component('DiscoveryRules', docUrl: external_link_path(type: 'plugin_manual', name: 'foreman_discovery', version: discovery_doc_version, section: '#4.3Automaticprovisioning') ) %>
|
15
|
+
<% end %>
|
data/config/routes.rb
CHANGED
@@ -7,6 +7,7 @@ Rails.application.routes.draw do
|
|
7
7
|
post 'medium_selected_discovered_hosts' => 'hosts#medium_selected'
|
8
8
|
|
9
9
|
get 'discovered_hosts/help', :action => :welcome, :controller => 'discovered_hosts'
|
10
|
+
get 'discovery_rules/help', :action => :welcome, :controller => 'discovery_rules'
|
10
11
|
|
11
12
|
constraints(:id => /[^\/]+/) do
|
12
13
|
resources :discovered_hosts, :except => [:new, :create] do
|
@@ -33,6 +34,7 @@ Rails.application.routes.draw do
|
|
33
34
|
|
34
35
|
resources :discovery_rules, :except => [:show] do
|
35
36
|
member do
|
37
|
+
get :clone
|
36
38
|
get :enable
|
37
39
|
get :disable
|
38
40
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# seeds UI notification blueprints that are supported by Disocvery.
|
2
2
|
[
|
3
3
|
{
|
4
|
-
group: _('
|
4
|
+
group: _('New hosts'),
|
5
5
|
name: 'new_discovered_host',
|
6
6
|
message: _('One or more hosts have been discovered'),
|
7
7
|
level: 'info',
|
@@ -10,8 +10,14 @@
|
|
10
10
|
links:
|
11
11
|
[
|
12
12
|
path_method: :discovered_hosts_path,
|
13
|
-
title: _('Details')
|
14
|
-
]
|
15
|
-
}
|
16
|
-
}
|
13
|
+
title: _('Details'),
|
14
|
+
],
|
15
|
+
},
|
16
|
+
},
|
17
|
+
{
|
18
|
+
group: _('Hosts'),
|
19
|
+
name: 'failed_discovery',
|
20
|
+
message: _('Error message goes here'),
|
21
|
+
level: 'error',
|
22
|
+
},
|
17
23
|
].each { |blueprint| UINotifications::Seed.new(blueprint).configure }
|
@@ -43,7 +43,7 @@ module ForemanDiscovery
|
|
43
43
|
|
44
44
|
initializer 'foreman_discovery.register_plugin', :before => :finisher_hook do |app|
|
45
45
|
Foreman::Plugin.register :foreman_discovery do
|
46
|
-
requires_foreman '>= 2.
|
46
|
+
requires_foreman '>= 2.4'
|
47
47
|
|
48
48
|
# discovered hosts permissions
|
49
49
|
security_block :discovery do
|
@@ -86,11 +86,11 @@ module ForemanDiscovery
|
|
86
86
|
# discovery rules permissions
|
87
87
|
security_block :discovery_rules do
|
88
88
|
permission :view_discovery_rules, {
|
89
|
-
:discovery_rules => [:index, :show, :auto_complete_search],
|
89
|
+
:discovery_rules => [:index, :show, :auto_complete_search, :welcome],
|
90
90
|
:"api/v2/discovery_rules" => [:index, :show]
|
91
91
|
}, :resource_type => 'DiscoveryRule'
|
92
92
|
permission :create_discovery_rules, {
|
93
|
-
:discovery_rules => [:new, :create],
|
93
|
+
:discovery_rules => [:new, :create, :clone],
|
94
94
|
:"api/v2/discovery_rules" => [:create]
|
95
95
|
}, :resource_type => 'DiscoveryRule'
|
96
96
|
permission :edit_discovery_rules, {
|
@@ -173,10 +173,6 @@ module ForemanDiscovery
|
|
173
173
|
# add dashboard widget
|
174
174
|
widget 'discovery_widget', :name=>N_('Discovered Hosts'), :sizex => 6, :sizey =>1
|
175
175
|
|
176
|
-
# allowed helpers and variables
|
177
|
-
allowed_template_helpers :rand
|
178
|
-
allowed_template_variables :kexec_kernel, :kexec_initrd
|
179
|
-
|
180
176
|
template_labels 'kexec' => N_('Discovery Kexec template')
|
181
177
|
|
182
178
|
# apipie API documentation
|
Binary file
|