foreman_discovery 3.0.0 → 4.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/controllers/api/v2/discovered_hosts_controller.rb +31 -11
- data/app/controllers/api/v2/discovery_rules_controller.rb +8 -16
- data/app/controllers/concerns/foreman/controller/discovered_extensions.rb +47 -2
- data/app/controllers/discovered_hosts_controller.rb +30 -55
- data/app/controllers/discovery_rules_controller.rb +2 -4
- data/app/helpers/discovered_hosts_helper.rb +27 -5
- data/app/lib/facter_utils.rb +18 -0
- data/app/lib/puppet_fact_parser_extensions.rb +18 -32
- data/app/models/discovery_rule.rb +33 -2
- data/app/models/host/discovered.rb +47 -61
- data/app/models/host/managed_extensions.rb +12 -3
- data/app/models/setting/discovered.rb +18 -6
- data/app/services/foreman_discovery/host_converter.rb +22 -0
- data/app/views/api/v2/discovered_hosts/main.json.rabl +1 -1
- data/app/views/api/v2/discovery_rules/main.json.rabl +6 -1
- data/app/views/api/v2/discovery_rules/show.json.rabl +4 -0
- data/app/views/dashboard/_discovery_widget.html.erb +6 -4
- data/app/views/dashboard/_discovery_widget_host.html.erb +4 -0
- data/app/views/dashboard/_discovery_widget_host_list.html.erb +2 -3
- data/app/views/discovered_hosts/_discovered_host.html.erb +3 -5
- data/app/views/discovered_hosts/_discovered_hosts_list.html.erb +7 -7
- data/app/views/discovered_hosts/index.html.erb +1 -0
- data/app/views/discovery_rules/_form.html.erb +51 -32
- data/config/routes.rb +4 -4
- data/db/migrate/20150310153859_remove_discovery_attribute_sets_from_managed_hosts.rb +8 -0
- data/db/migrate/20150331132115_remove_old_permissions.rb +16 -0
- data/db/migrate/20150505111345_remove_leftover_tokens.rb +13 -0
- data/db/migrate/20150512150432_remove_old_discovery_reader_permissions.rb +10 -0
- data/db/migrate/20150714144500_review_discovery_permissions.rb +17 -0
- data/lib/foreman_discovery/engine.rb +46 -16
- data/lib/foreman_discovery/version.rb +1 -1
- data/locale/de/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/de/foreman_discovery.po +74 -72
- data/locale/de/foreman_discovery.pox +40 -0
- data/locale/en_GB/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en_GB/foreman_discovery.po +90 -88
- data/locale/en_GB/foreman_discovery.pox +0 -0
- data/locale/es/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/es/foreman_discovery.po +3 -3
- data/locale/es/foreman_discovery.pox +41 -0
- data/locale/fr/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/fr/foreman_discovery.po +3 -3
- data/locale/fr/foreman_discovery.pox +69 -0
- data/locale/gl/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/gl/foreman_discovery.po +3 -3
- data/locale/gl/foreman_discovery.pox +21 -0
- data/locale/it/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/it/foreman_discovery.po +3 -3
- data/locale/it/foreman_discovery.pox +0 -0
- data/locale/ja/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ja/foreman_discovery.po +67 -66
- data/locale/ja/foreman_discovery.pox +29 -0
- data/locale/ko/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ko/foreman_discovery.po +3 -3
- data/locale/ko/foreman_discovery.pox +189 -0
- data/locale/messages.mo +0 -0
- data/locale/pt_BR/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/pt_BR/foreman_discovery.po +7 -7
- data/locale/pt_BR/foreman_discovery.pox +0 -0
- data/locale/ru/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ru/foreman_discovery.po +98 -96
- data/locale/ru/foreman_discovery.pox +0 -0
- data/locale/sv_SE/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/sv_SE/foreman_discovery.po +3 -3
- data/locale/zh_CN/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_CN/foreman_discovery.po +3 -3
- data/locale/zh_CN/foreman_discovery.pox +33 -0
- data/locale/zh_TW/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_TW/foreman_discovery.po +3 -3
- data/locale/zh_TW/foreman_discovery.pox +23 -0
- data/test/functional/api/v2/discovered_hosts_controller_test.rb +45 -7
- data/test/functional/discovered_hosts_controller_test.rb +52 -11
- data/test/unit/discovered_extensions_test.rb +40 -17
- data/test/unit/discovery_rule_test.rb +59 -0
- data/test/unit/host_discovered_test.rb +69 -6
- data/test/unit/puppet_fact_parser_extensions_test.rb +55 -40
- metadata +103 -81
- data/app/services/host_converter.rb +0 -30
@@ -3,9 +3,6 @@ require 'foreman_discovery/proxy_operations'
|
|
3
3
|
class Host::Discovered < ::Host::Base
|
4
4
|
include ScopedSearchExtensions
|
5
5
|
|
6
|
-
belongs_to :location
|
7
|
-
belongs_to :organization
|
8
|
-
belongs_to :subnet
|
9
6
|
belongs_to :hostgroup
|
10
7
|
has_one :discovery_attribute_set, :foreign_key => :host_id, :dependent => :destroy
|
11
8
|
|
@@ -13,71 +10,46 @@ class Host::Discovered < ::Host::Base
|
|
13
10
|
|
14
11
|
delegate :memory, :cpu_count, :disk_count, :disks_size, :to => :discovery_attribute_set
|
15
12
|
|
16
|
-
scoped_search :on => :name, :complete_value => true
|
13
|
+
scoped_search :on => :name, :complete_value => true
|
14
|
+
scoped_search :on => :created_at, :default_order => :desc
|
17
15
|
scoped_search :on => :last_report, :complete_value => true
|
18
|
-
scoped_search :on => :ip, :complete_value => true
|
19
|
-
scoped_search :on => :mac, :complete_value => true
|
16
|
+
scoped_search :in => :primary_interface, :on => :ip, :complete_value => true
|
17
|
+
scoped_search :in => :primary_interface, :on => :mac, :complete_value => true
|
20
18
|
scoped_search :in => :model, :on => :name, :complete_value => true, :rename => :model
|
21
19
|
scoped_search :in => :fact_values, :on => :value, :in_key => :fact_names, :on_key => :name, :rename => :facts, :complete_value => true, :only_explicit => true
|
22
20
|
scoped_search :in => :location, :on => :name, :rename => :location, :complete_value => true if SETTINGS[:locations_enabled]
|
23
21
|
scoped_search :in => :organization, :on => :name, :rename => :organization, :complete_value => true if SETTINGS[:organizations_enabled]
|
24
22
|
scoped_search :in => :subnet, :on => :network, :complete_value => true, :rename => :subnet
|
23
|
+
scoped_search :in => :subnet, :on => :name, :complete_value => true, :rename => 'subnet.name'
|
25
24
|
scoped_search :in => :discovery_attribute_set, :on => :cpu_count, :rename => :cpu_count, :complete_value => true, :only_explicit => true
|
26
25
|
scoped_search :in => :discovery_attribute_set, :on => :memory, :rename => :memory, :complete_value => true, :only_explicit => true
|
27
26
|
scoped_search :in => :discovery_attribute_set, :on => :disk_count, :rename => :disk_count, :complete_value => true, :only_explicit => true
|
28
27
|
scoped_search :in => :discovery_attribute_set, :on => :disks_size, :rename => :disks_size, :complete_value => true, :only_explicit => true
|
29
28
|
|
30
29
|
default_scope lambda {
|
31
|
-
|
32
|
-
loc = Location.current
|
33
|
-
conditions = {}
|
34
|
-
conditions[:organization_id] = org.subtree_ids if org
|
35
|
-
conditions[:location_id] = loc.subtree_ids if loc
|
36
|
-
where(conditions)
|
30
|
+
where(taxonomy_conditions).order("hosts.created_at DESC")
|
37
31
|
}
|
38
32
|
|
39
33
|
def self.import_host_and_facts facts
|
40
34
|
raise(::Foreman::Exception.new(N_("Invalid facts, must be a Hash"))) unless facts.is_a?(Hash)
|
41
|
-
fact_name = Setting[:discovery_fact] || 'discovery_bootif'
|
42
|
-
prefix_from_settings = Setting[:discovery_prefix]
|
43
|
-
hostname_prefix = prefix_from_settings if prefix_from_settings.present? && prefix_from_settings.match(/^[a-zA-Z].*/)
|
44
|
-
hostname_prefix ||= 'mac'
|
45
|
-
hostname = facts[fact_name].try(:downcase).try(:gsub,/:/,'').try(:sub,/^/, hostname_prefix)
|
46
|
-
raise(::Foreman::Exception.new(N_("Invalid facts: hash does not contain the required fact '%s'"), fact_name)) unless hostname
|
47
|
-
raise(::Foreman::Exception.new(N_("Invalid facts: hash does not contain IP address"))) unless facts['ipaddress']
|
48
35
|
|
49
36
|
# filter facts
|
50
37
|
facts.reject!{|k,v| k =~ /kernel|operatingsystem|osfamily|ruby|path|time|swap|free|filesystem/i }
|
51
38
|
|
39
|
+
raise ::Foreman::Exception.new(N_("Expected discovery_fact '%s' is missing, unable to detect primary interface and set hostname") % FacterUtils::bootif_name) unless FacterUtils::bootif_present(facts)
|
40
|
+
|
41
|
+
# construct hostname
|
42
|
+
prefix_from_settings = Setting[:discovery_prefix]
|
43
|
+
hostname_prefix = prefix_from_settings if prefix_from_settings.present? && prefix_from_settings.match(/^[a-zA-Z].*/)
|
44
|
+
hostname_prefix ||= 'mac'
|
45
|
+
hostname = FacterUtils::bootif_mac(facts).try(:downcase).try(:gsub,/:/,'').try(:sub,/^/, hostname_prefix)
|
46
|
+
|
47
|
+
# create new host record
|
52
48
|
h = ::Host::Discovered.find_by_name hostname
|
53
49
|
h ||= Host.new :name => hostname, :type => "Host::Discovered"
|
54
50
|
h.type = "Host::Discovered"
|
55
51
|
|
56
|
-
|
57
|
-
begin
|
58
|
-
macfact = Net::Validations.normalize_mac(macfact)
|
59
|
-
rescue ArgumentError => e
|
60
|
-
macfact = facts['discovery_bootif'].try(:downcase)
|
61
|
-
h.name = facts['discovery_bootif'].try(:downcase).try(:gsub,/:/,'').try(:sub,/^/, hostname_prefix)
|
62
|
-
end
|
63
|
-
h.mac = macfact
|
64
|
-
|
65
|
-
|
66
|
-
if SETTINGS[:locations_enabled]
|
67
|
-
begin
|
68
|
-
h.location = (Location.find_by_name Setting[:discovery_location]) || Location.first
|
69
|
-
rescue
|
70
|
-
h.location = Location.first
|
71
|
-
end
|
72
|
-
end
|
73
|
-
if SETTINGS[:organizations_enabled]
|
74
|
-
begin
|
75
|
-
h.organization = (Organization.find_by_name Setting[:discovery_organization]) || Organization.first
|
76
|
-
rescue
|
77
|
-
h.organization = Organization.first
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
52
|
+
# and save (interfaces are created via puppet parser extension)
|
81
53
|
h.save(:validate => false) if h.new_record?
|
82
54
|
state = h.import_facts(facts)
|
83
55
|
return h, state
|
@@ -100,17 +72,35 @@ class Host::Discovered < ::Host::Base
|
|
100
72
|
super
|
101
73
|
end
|
102
74
|
|
103
|
-
def populate_fields_from_facts
|
104
|
-
#
|
105
|
-
|
106
|
-
|
75
|
+
def populate_fields_from_facts(facts = self.facts_hash, type = 'puppet')
|
76
|
+
# detect interfaces and primary interface using extensions
|
77
|
+
parser = super(facts, type)
|
78
|
+
|
79
|
+
# set additional discovery attributes
|
80
|
+
primary_ip = self.primary_interface.ip
|
81
|
+
unless primary_ip.nil?
|
82
|
+
subnet = Subnet.subnet_for(primary_ip)
|
83
|
+
Rails.logger.warn "Subnet not detected for #{primary_ip}" if subnet.nil?
|
84
|
+
# set subnet
|
85
|
+
self.primary_interface.subnet = subnet
|
86
|
+
# set location and organization
|
87
|
+
if SETTINGS[:locations_enabled]
|
88
|
+
self.location = Location.find_by_name(Setting[:discovery_location]) ||
|
89
|
+
subnet.try(:locations).try(:first) ||
|
90
|
+
Location.first
|
91
|
+
end
|
92
|
+
if SETTINGS[:organizations_enabled]
|
93
|
+
self.organization = Organization.find_by_name(Setting[:discovery_organization]) ||
|
94
|
+
subnet.try(:organizations).try(:first) ||
|
95
|
+
Organization.first
|
96
|
+
end
|
107
97
|
else
|
108
|
-
|
98
|
+
raise(::Foreman::Exception.new(N_("Unable to assign subnet, primary interface is missing IP address")))
|
109
99
|
end
|
110
|
-
self.primary_interface.subnet = Subnet.subnet_for(self.primary_interface.ip)
|
111
100
|
self.discovery_attribute_set = DiscoveryAttributeSet.where(:host_id => id).first_or_create
|
112
101
|
self.discovery_attribute_set.update_attributes(import_from_facts)
|
113
|
-
self.save
|
102
|
+
self.save!
|
103
|
+
parser
|
114
104
|
end
|
115
105
|
|
116
106
|
def import_from_facts(facts = self.facts_hash)
|
@@ -160,18 +150,14 @@ class Host::Discovered < ::Host::Base
|
|
160
150
|
proxy_url = self.proxy_url
|
161
151
|
|
162
152
|
if proxy_url[:type] == 'proxy'
|
163
|
-
|
153
|
+
ForemanDiscovery::ProxyOperations.new(:url => proxy_url[:url], :operation => 'reboot').
|
154
|
+
parse_put_operation.try(:fetch, 'result')
|
164
155
|
else
|
165
|
-
|
156
|
+
::ProxyAPI::BMC.new(:url => "http://#{self.ip}:8443").power :action => "cycle"
|
166
157
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
status
|
171
|
-
rescue => e
|
172
|
-
logger.info "ForemanDiscovery: reboot result: failed"
|
173
|
-
logger.warn e.backtrace.join('\n')
|
174
|
-
raise e
|
158
|
+
rescue => e
|
159
|
+
::Foreman::Logging.exception("Unable to reboot #{name}", e)
|
160
|
+
raise ::Foreman::WrappedException.new(e, N_("Unable to reboot %{name}: %{msg}"), :name => name, :msg => e.to_s)
|
175
161
|
end
|
176
162
|
|
177
163
|
def self.model_name
|
@@ -4,24 +4,33 @@ module Host::ManagedExtensions
|
|
4
4
|
included do
|
5
5
|
# execute standard callbacks
|
6
6
|
after_validation :queue_reboot
|
7
|
+
after_save :delete_discovery_attribute_set
|
7
8
|
|
8
9
|
belongs_to :discovery_rule
|
9
10
|
end
|
10
11
|
|
11
12
|
def queue_reboot
|
13
|
+
return unless errors.empty? && Setting[:discovery_reboot]
|
12
14
|
return if new_record? # Discovered Hosts already exist, and new_records will break `find`
|
13
15
|
return unless type_changed? and ::Host::Base.find(self.id).type == "Host::Discovered"
|
16
|
+
# reboot task must be high priority and there is no compensation action apparently
|
14
17
|
post_queue.create(:name => _("Rebooting %s") % self, :priority => 10000,
|
15
18
|
:action => [self, :setReboot])
|
16
19
|
end
|
17
20
|
|
18
21
|
def setReboot
|
19
22
|
old.becomes(Host::Discovered).reboot
|
23
|
+
# It is too late to report error in the post_queue, we catch them and
|
24
|
+
# continue. If flash is implemented for new hosts (http://projects.theforeman.org/issues/10559)
|
25
|
+
# we can report the error to the user perhaps.
|
26
|
+
true
|
27
|
+
rescue ::Foreman::Exception
|
28
|
+
true
|
20
29
|
end
|
21
30
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
31
|
+
def delete_discovery_attribute_set
|
32
|
+
return if new_record?
|
33
|
+
DiscoveryAttributeSet.destroy_all(:host_id => self.id) if type_changed?
|
25
34
|
end
|
26
35
|
|
27
36
|
end
|
@@ -9,34 +9,35 @@ class Setting::Discovered < ::Setting
|
|
9
9
|
|
10
10
|
Setting.transaction do
|
11
11
|
[
|
12
|
-
self.set('discovery_fact',
|
13
|
-
self.set('discovery_auto',
|
12
|
+
self.set('discovery_fact', N_("Fact name to use for primary interface detection and hostname"), "discovery_bootif"),
|
13
|
+
self.set('discovery_auto', N_("Automatically provision newly discovered hosts, according to the provisioning rules"), false),
|
14
|
+
self.set('discovery_reboot', N_("Automatically reboot discovered host during provisioning"), true),
|
14
15
|
].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
|
15
16
|
end
|
16
17
|
|
17
18
|
Setting.transaction do
|
18
19
|
[
|
19
|
-
self.set('discovery_prefix',
|
20
|
+
self.set('discovery_prefix', N_("The default prefix to use for the host name, must start with a letter"), "mac"),
|
20
21
|
].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
|
21
22
|
end
|
22
23
|
|
23
24
|
Setting.transaction do
|
24
25
|
[
|
25
|
-
self.set('discovery_fact_column',
|
26
|
+
self.set('discovery_fact_column', N_("Extra facter columns to show in host lists (separate by comma)"), ""),
|
26
27
|
].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
|
27
28
|
end
|
28
29
|
|
29
30
|
if SETTINGS[:locations_enabled]
|
30
31
|
Setting.transaction do
|
31
32
|
[
|
32
|
-
self.set('discovery_location',
|
33
|
+
self.set('discovery_location', N_("The default location to place discovered hosts in"), ""),
|
33
34
|
].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
|
34
35
|
end
|
35
36
|
end
|
36
37
|
if SETTINGS[:organizations_enabled]
|
37
38
|
Setting.transaction do
|
38
39
|
[
|
39
|
-
self.set('discovery_organization',
|
40
|
+
self.set('discovery_organization', N_("The default organization to place discovered hosts in"), "" ),
|
40
41
|
].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
|
41
42
|
end
|
42
43
|
end
|
@@ -45,4 +46,15 @@ class Setting::Discovered < ::Setting
|
|
45
46
|
|
46
47
|
end
|
47
48
|
|
49
|
+
def self.discovery_fact_column_array
|
50
|
+
return [] if !Setting['discovery_fact_column'].present?
|
51
|
+
list = []
|
52
|
+
Setting['discovery_fact_column'].to_s.split(",").each do |value|
|
53
|
+
list << value.strip
|
54
|
+
end
|
55
|
+
rescue => error
|
56
|
+
logger.warn "Failed to parse comma delimited list [%s] into array. Error: %s" % [list,error]
|
57
|
+
ensure
|
58
|
+
list
|
59
|
+
end
|
48
60
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class ForemanDiscovery::HostConverter
|
2
|
+
|
3
|
+
# Converts discovered host to managed host without uptading the database.
|
4
|
+
# Record must be saved explicitly (using save! or update_attributes! or similar).
|
5
|
+
# This method MUST be called from a SQL transaction.
|
6
|
+
def self.to_managed(original_host, set_managed = true, set_build = true)
|
7
|
+
if ActiveRecord::Base.connection.open_transactions <= 0
|
8
|
+
raise "This method must be executed with explicit transaction"
|
9
|
+
end
|
10
|
+
host = original_host.becomes(::Host::Managed)
|
11
|
+
host.type = 'Host::Managed'
|
12
|
+
# the following flags can be skipped when parameters are set to false
|
13
|
+
if set_managed
|
14
|
+
host.managed = set_managed
|
15
|
+
host.primary_interface.managed = set_managed
|
16
|
+
end
|
17
|
+
# set build only and only on final save (otherwise interfaces are not being identified)
|
18
|
+
host.build = set_build if set_build
|
19
|
+
host
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -2,7 +2,7 @@ object @discovered_host
|
|
2
2
|
|
3
3
|
extends "api/v2/discovered_hosts/base"
|
4
4
|
|
5
|
-
attributes :ip, :mac, :last_report, :subnet_id, :subnet_name, :memory, :disk_count, :disks_size
|
5
|
+
attributes :ip, :mac, :last_report, :subnet_id, :subnet_name, :model_name, :memory, :disk_count, :disks_size
|
6
6
|
attribute :cpu_count => :cpus
|
7
7
|
|
8
8
|
if SETTINGS[:organizations_enabled]
|
@@ -2,4 +2,9 @@ object @discovery_rule
|
|
2
2
|
|
3
3
|
extends "api/v2/discovery_rules/base"
|
4
4
|
|
5
|
-
attributes :name, :enabled, :hostgroup_id, :
|
5
|
+
attributes :name, :enabled, :hostgroup_id, :hostgroup_name, :hostname, :priority, :search
|
6
|
+
attribute :max_count => :hosts_limit
|
7
|
+
|
8
|
+
child :hosts do
|
9
|
+
extends "api/v2/discovered_hosts/base"
|
10
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
|
-
<h4 class="ca"><%= _('Discovered Host Pool') %> - <%= @current_permission %></h4>
|
2
1
|
<% all_hosts = Host::Discovered.includes(:model).includes(:discovery_attribute_set).scoped %>
|
3
|
-
<% hosts = all_hosts.limit(
|
2
|
+
<% hosts = all_hosts.limit(6) %>
|
3
|
+
|
4
|
+
<h4 class="header">
|
5
|
+
<%= link_to "#{all_hosts.size} #{n_('Discovered Host', 'Discovered Hosts', all_hosts.size)}", discovered_hosts_path %>
|
6
|
+
</h4>
|
7
|
+
|
4
8
|
<% if hosts.empty? %>
|
5
9
|
<p class="ca"><%= _("No discovered hosts available") %></p>
|
6
10
|
<% else %>
|
7
11
|
<%= render :partial => 'discovery_widget_host_list', :locals => { :hosts => hosts } %>
|
8
|
-
<p class="ca"><%= link_to n_("Total pool size", "Total pool size", all_hosts.size), discovered_hosts_path %>
|
9
|
-
- <%= all_hosts.size %> </p>
|
10
12
|
<% end %>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<td><%= discovery_status_icon(host) %> <%= link_to trunc_with_tooltip(h(host.name)), discovered_host_path(host) %></td>
|
2
|
+
<td class="hidden-tablet hidden-xs"><%= model_name host %></td>
|
3
|
+
<td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :cpu_count) %></td>
|
4
|
+
<td class="hidden-tablet hidden-xs"><%= number_to_human_size(discovery_attribute(host, :memory, 0) * 1024 * 1024) %></td>
|
@@ -2,15 +2,14 @@
|
|
2
2
|
<thead>
|
3
3
|
<th><%= _('Host') %></th>
|
4
4
|
<th><%= _('Model') %></th>
|
5
|
-
<th><%= _('IP Address') %></th>
|
6
5
|
<th><%= _('CPUs') %></th>
|
7
6
|
<th><%= _('Memory') %></th>
|
8
7
|
</thead>
|
9
8
|
<tbody>
|
10
9
|
<% hosts.each do |host| %>
|
11
10
|
<tr>
|
12
|
-
<%= render :partial => "
|
13
|
-
:host => host
|
11
|
+
<%= render :partial => "discovery_widget_host", :locals => {
|
12
|
+
:host => host } %>
|
14
13
|
</tr>
|
15
14
|
<% end %>
|
16
15
|
</tbody>
|
@@ -1,12 +1,10 @@
|
|
1
|
-
<td><%= link_to trunc_with_tooltip(h(host.name)), discovered_host_path(host) %></td>
|
1
|
+
<td><%= discovery_status_icon(host) %> <%= link_to trunc_with_tooltip(h(host.name)), discovered_host_path(host) %></td>
|
2
2
|
<td class="hidden-tablet hidden-xs"><%= model_name host %></td>
|
3
3
|
<td class="hidden-tablet hidden-xs"><%= host.ip %></td>
|
4
4
|
<td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :cpu_count) %></td>
|
5
5
|
<td class="hidden-tablet hidden-xs"><%= number_to_human_size(discovery_attribute(host, :memory, 0) * 1024 * 1024) %></td>
|
6
|
-
<% unless defined? hide_disk %>
|
7
6
|
<td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :disk_count) %></td>
|
8
7
|
<td class="hidden-tablet hidden-xs"><%= number_to_human_size(discovery_attribute(host, :disks_size, 0) * 1024 * 1024) %></td>
|
9
|
-
<%
|
10
|
-
|
11
|
-
<% end %>
|
8
|
+
<% Setting::Discovered.discovery_fact_column_array.each do |fact_column| %>
|
9
|
+
<td class="hidden-tablet hidden-xs"><%= host.facts_hash[fact_column.strip] || 'N/A' %></td>
|
12
10
|
<% end %>
|
@@ -10,8 +10,8 @@
|
|
10
10
|
<th class="hidden-tablet hidden-xs"><%= sort :memory, :as => _('Memory') %></th>
|
11
11
|
<th class="hidden-tablet hidden-xs"><%= sort :disk_count, :as => _('Disk count') %></th>
|
12
12
|
<th class="hidden-tablet hidden-xs"><%= sort :disks_size, :as => _('Disks size') %></th>
|
13
|
-
<%
|
14
|
-
<th class="hidden-tablet hidden-xs"><%=
|
13
|
+
<% Setting::Discovered.discovery_fact_column_array.each do |fact_column| %>
|
14
|
+
<th class="hidden-tablet hidden-xs"><%= fact_column.strip.capitalize %></th>
|
15
15
|
<% end %>
|
16
16
|
<% if SETTINGS[:locations_enabled] -%>
|
17
17
|
<th class="hidden-tablet hidden-xs"><%= sort :location, :as => _('Location') %></th>
|
@@ -26,7 +26,7 @@
|
|
26
26
|
<% @hosts.each do |host| -%>
|
27
27
|
<tr>
|
28
28
|
<td class="ca">
|
29
|
-
<%= check_box_tag "host_ids[]", nil, false, :id => "host_ids_#{host.id}", :disabled => !
|
29
|
+
<%= check_box_tag "host_ids[]", nil, false, :id => "host_ids_#{host.id}", :disabled => !authorized_for_edit_destroy?, :class => 'host_select_boxes', :onclick => 'hostChecked(this)' -%>
|
30
30
|
</td>
|
31
31
|
<%= render :partial => "discovered_host", :locals => {:host => host} %>
|
32
32
|
<% if SETTINGS[:locations_enabled] -%>
|
@@ -39,10 +39,10 @@
|
|
39
39
|
<td class="hidden-tablet hidden-xs"><%= disc_report_column(host) %></td>
|
40
40
|
<td>
|
41
41
|
<%= action_buttons(
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
display_link_if_authorized(_("Provision"), hash_for_edit_discovered_host_path(:id => host)),
|
43
|
+
display_link_if_authorized(_("Auto Provision"), hash_for_auto_provision_discovered_host_path(:id => host), :method => :post),
|
44
|
+
display_link_if_authorized(_("Refresh facts"), hash_for_refresh_facts_discovered_host_path(:id => host)),
|
45
|
+
display_link_if_authorized(_("Reboot"), hash_for_reboot_discovered_host_path(:id => host), :method => :put),
|
46
46
|
display_delete_if_authorized(hash_for_discovered_host_path(:id => host), :confirm => _("Delete %s?") % host.name, :action => :destroy))%>
|
47
47
|
</td>
|
48
48
|
</tr>
|
@@ -1,3 +1,4 @@
|
|
1
1
|
<% title_actions multiple_discovered_hosts_actions_select -%>
|
2
|
+
<% title_actions display_link_if_authorized(_("Reboot All"), hash_for_reboot_all_discovered_hosts_path, {:method => :put, :disabled => @hosts.empty?}) %>
|
2
3
|
<% title_actions display_link_if_authorized(_("Auto Provision All"), hash_for_auto_provision_all_discovered_hosts_path, {:method => :post, :disabled => @hosts.empty?}) %>
|
3
4
|
<%= render 'discovered_hosts_list' %>
|
@@ -1,34 +1,53 @@
|
|
1
1
|
<%= form_for @discovery_rule, :url => (@discovery_rule.new_record? ? discovery_rules_path : discovery_rule_path(:id => @discovery_rule.id)) do |f| %>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
2
|
+
<%= base_errors_for @discovery_rule %>
|
3
|
+
|
4
|
+
<ul class="nav nav-tabs" data-tabs="tabs">
|
5
|
+
<li class="active"><a href="#primary" data-toggle="tab"><%= _('Primary') %></a></li>
|
6
|
+
<% if show_location_tab? %>
|
7
|
+
<li><a href="#locations" data-toggle="tab"><%= _('Locations') %></a></li>
|
8
|
+
<% end %>
|
9
|
+
<% if show_organization_tab? %>
|
10
|
+
<li><a href="#organizations" data-toggle="tab"><%= _('Organizations') %></a></li>
|
11
|
+
<% end %>
|
12
|
+
</ul>
|
13
|
+
|
14
|
+
<div class="tab-content">
|
15
|
+
|
16
|
+
<div class="tab-pane active" id="primary">
|
17
|
+
<%= text_f f, :name %>
|
18
|
+
<%= autocomplete_f f, :search,
|
19
|
+
:path => "discovered_hosts",
|
20
|
+
:control_group_id => 'search_group', :size => 'col-md-9' %>
|
21
|
+
<%= select_f f, :hostgroup_id, accessible_hostgroups, :id, :to_label, { :include_blank => false },
|
22
|
+
{ :help_inline => _('Target host group for this rule with all properties set') } %>
|
23
|
+
<%= text_f f, :hostname, :help_inline => popover(
|
24
|
+
_("Template"),
|
25
|
+
"<div>" +
|
26
|
+
_("Specify target hostname template pattern in the same syntax as in Provisioning Templates (ERB).") +
|
27
|
+
"</div>"+
|
28
|
+
"<div>" +
|
29
|
+
_("Domain will be appended automatically. A hostname based on MAC address will be used when left blank. In addition to @host attribute function rand for random integers is available. Examples:") +
|
30
|
+
"</div>"+
|
31
|
+
"<pre>"+
|
32
|
+
"myhost-<%= rand(99999) %>" + "\n\n" +
|
33
|
+
"abc-<%= @host.facts['bios_vendor'] + " + "\n" +
|
34
|
+
" '-' + rand(99999) %>" + "\n\n" +
|
35
|
+
"xyz-<%= @host.hostgroup.name %>" + "\n\n" +
|
36
|
+
"srv-<%= @host.discovery_rule.name %>" + "\n\n" +
|
37
|
+
"server-<%= @host.ip.gsub('.','-') + " + "\n" +
|
38
|
+
" '-' + @host.hostgroup.subnet.name %>" + "\n" +
|
39
|
+
"</pre>"+
|
40
|
+
"</div>"+
|
41
|
+
"<div>"+
|
42
|
+
_("When creating hostname patterns, make sure the resulting host names are unique. Hostnames must not start with numbers. A good approach is to use unique information provided by facter (MAC address, BIOS or serial ID).") +
|
43
|
+
"</div>", :title => _("Hostname for provisioned hosts")).html_safe %>
|
44
|
+
<%= text_f f, :max_count, :label => _('Hosts limit'), :help_inline => _('Maximum hosts provisioned with this rule (0 = unlimited)') %>
|
45
|
+
<%= text_f f, :priority, :help_inline => _('Rule priority (lower integer means higher priority)') %>
|
46
|
+
<%= checkbox_f f, :enabled %>
|
47
|
+
</div>
|
48
|
+
<% if show_taxonomy_tabs? %>
|
49
|
+
<%= render 'taxonomies/loc_org_tabs', :f => f, :obj => @discovery_rule %>
|
50
|
+
<% end %>
|
51
|
+
</div>
|
52
|
+
<%= submit_or_cancel f %>
|
34
53
|
<% end %>
|
data/config/routes.rb
CHANGED
@@ -7,7 +7,7 @@ Rails.application.routes.draw do
|
|
7
7
|
match 'medium_selected_discovered_hosts' => 'hosts#medium_selected'
|
8
8
|
|
9
9
|
constraints(:id => /[^\/]+/) do
|
10
|
-
resources :discovered_hosts do
|
10
|
+
resources :discovered_hosts, :except => [:new, :create] do
|
11
11
|
member do
|
12
12
|
get 'refresh_facts'
|
13
13
|
put 'reboot'
|
@@ -22,6 +22,7 @@ Rails.application.routes.draw do
|
|
22
22
|
post 'update_multiple_location'
|
23
23
|
get 'auto_complete_search'
|
24
24
|
post 'auto_provision_all'
|
25
|
+
put 'reboot_all'
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
@@ -40,13 +41,12 @@ Rails.application.routes.draw do
|
|
40
41
|
member do
|
41
42
|
post 'auto_provision'
|
42
43
|
put 'reboot'
|
44
|
+
put 'refresh_facts'
|
43
45
|
end
|
44
46
|
collection do
|
45
47
|
post 'facts'
|
46
48
|
post 'auto_provision_all'
|
47
|
-
|
48
|
-
member do
|
49
|
-
put 'refresh_facts'
|
49
|
+
put 'reboot_all'
|
50
50
|
end
|
51
51
|
end
|
52
52
|
resources :discovery_rules, :except => [:new, :edit]
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class RemoveDiscoveryAttributeSetsFromManagedHosts < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
DiscoveryAttributeSet.where(:id => DiscoveryAttributeSet.joins(:host).where(:'hosts.managed' => true).pluck("#{DiscoveryAttributeSet.table_name}.id")).delete_all
|
4
|
+
end
|
5
|
+
|
6
|
+
def down
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class RemoveOldPermissions < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
# remove invalid permissions causing http://projects.theforeman.org/issues/9963
|
4
|
+
perms = Permission.where("name like '%_discovered_hosts' and resource_type is null").destroy_all
|
5
|
+
say "Removed invalid permissions: #{perms.inspect}" if perms.size > 0
|
6
|
+
|
7
|
+
# unassociate and remove unused role "Discovery" (renamed to "Discovery Manager")
|
8
|
+
if old_role = Role.where(:name => "Discovery").first
|
9
|
+
UserRole.where(:role_id => old_role.id).destroy_all
|
10
|
+
say "Role 'Discovery' was removed, use 'Discovery Manager' instead" if old_role.destroy
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class RemoveLeftoverTokens < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
existing_tokens = Host::Managed.all.map(&:token).compact
|
4
|
+
if existing_tokens.empty?
|
5
|
+
Token.delete_all
|
6
|
+
else
|
7
|
+
Token.where('id not in (?)', existing_tokens).delete_all
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def down
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class RemoveOldDiscoveryReaderPermissions < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
Permission.where("name like '%_discovery_rules' and resource_type is null").each do |permission|
|
4
|
+
permission.update_attributes(:resource_type => 'DiscoveryRule')
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def down
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class ReviewDiscoveryPermissions < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
if (mgr = Role.find_by_name("Discovery Manager"))
|
4
|
+
perms = []
|
5
|
+
perms << "submit_discovered_hosts" if Permission.find_by_name("edit_discovered_hosts")
|
6
|
+
perms << "auto_provision_discovered_hosts" if Permission.find_by_name("provision_discovered_hosts")
|
7
|
+
perms << "create_discovery_rules" if Permission.find_by_name("new_discovery_rules")
|
8
|
+
perms << "destroy_discovery_rules" if Permission.find_by_name("delete_discovery_rules")
|
9
|
+
mgr.add_permissions!(perms)
|
10
|
+
end
|
11
|
+
Permission.find_by_name("new_discovery_rules").try(:destroy)
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
# rollback is not supported
|
16
|
+
end
|
17
|
+
end
|