foreman_discovery 3.0.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|