foreman_discovery 25.0.1 → 25.1.0
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 +2 -0
- data/app/controllers/concerns/foreman/controller/parameters/discovered_host.rb +41 -35
- data/app/controllers/concerns/foreman/controller/parameters/discovery_rule.rb +18 -12
- data/app/controllers/discovered_hosts_controller.rb +0 -13
- data/app/controllers/discovered_hosts_controller.rb.orig +354 -0
- data/app/models/host/discovered.rb +1 -0
- data/app/services/foreman_discovery/fact_to_category_resolver.rb +11 -6
- data/app/services/foreman_discovery/lldp_neighbors.rb +6 -2
- data/app/views/api/v2/discovered_hosts/main.json.rabl +2 -1
- data/app/views/discovered_hosts/_discovered_host.html.erb +1 -0
- data/app/views/discovered_hosts/_discovered_hosts_list.html.erb +2 -1
- data/app/views/discovered_hosts/show.html.erb +3 -1
- data/app/views/discovered_mailer/_discovered_host.html.erb +5 -0
- data/lib/foreman_discovery/version.rb +1 -1
- data/test/facts/facts_with_lldp_bond_candidate.json +7 -0
- data/test/functional/api/v2/discovered_hosts_controller_test.rb +35 -0
- data/test/test_helper_discovery.rb +21 -7
- data/test/unit/lldp_neighbors_test.rb +34 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95cebd63e44a4dd37542e995996eff81ed31f0b4b93039298abd37a3a0c83910
|
4
|
+
data.tar.gz: 978901f1f25b3e01b30a701d65f96242bec71847b38bd5b7901bcc7778a19628
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1b8e43d7343136d97407726f69297c1e84c809d189a35ae6941db6ec90b8de5be3443e349ca4af0dd9b555417434d6b082297d972385ecde2748606b98df4e2
|
7
|
+
data.tar.gz: afa86dba8270f1f29f2ceb4edb68dbfba7fa722e4bec342f8a08d69a6ff51c028714b343f77db188fdc59f2d48fa4968b4a44c3ea00bd34f65e7b2c25d511a84
|
@@ -53,6 +53,7 @@ module Api
|
|
53
53
|
param :name, String
|
54
54
|
param :environment_id, String, :desc => N_("required if host is managed and value is not inherited from host group")
|
55
55
|
param :ip, String, :desc => N_("not required if using a subnet with DHCP proxy")
|
56
|
+
param :ip6, String, :desc => N_("not required if using an IPv6 subnet with DHCP proxy")
|
56
57
|
param :mac, String, :desc => N_("not required if it's a virtual machine")
|
57
58
|
param :architecture_id, :number, :desc => N_("required if host is managed and value is not inherited from host group")
|
58
59
|
param :domain_id, :number, :desc => N_("required if host is managed and value is not inherited from host group")
|
@@ -62,6 +63,7 @@ module Api
|
|
62
63
|
param :medium_id, String, :desc => N_("required if not imaged based provisioning and host is managed and value is not inherited from host group")
|
63
64
|
param :ptable_id, :number, :desc => N_("required if host is managed and custom partition has not been defined")
|
64
65
|
param :subnet_id, :number, :desc => N_("required if host is managed and value is not inherited from host group")
|
66
|
+
param :subnet6_id, :number, :desc => N_("required if host is managed, does not have IPv4 IP / Subnet, or the value is not inherited from the host group")
|
65
67
|
param :sp_subnet_id, :number
|
66
68
|
param :model_id, :number
|
67
69
|
param :hostgroup_id, :number
|
@@ -1,43 +1,49 @@
|
|
1
|
-
module Foreman
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Foreman
|
2
|
+
module Controller
|
3
|
+
module Parameters
|
4
|
+
module DiscoveredHost
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Foreman::Controller::Parameters::Host
|
7
|
+
if defined?(ForemanPuppet)
|
8
|
+
include ForemanPuppet::Extensions::ParametersHost
|
9
|
+
end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
class_methods do
|
12
|
+
def discovered_host_params_filter
|
13
|
+
Foreman::ParameterFilter.new(::Host::Discovered).tap do |filter|
|
14
|
+
filter.permit :discovery_rule_id
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
add_host_base_params_filter(filter)
|
17
|
+
add_host_common_params_filter(filter)
|
18
|
+
add_host_puppet_params_filter(filter) if defined?(ForemanPuppet)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
def discovered_host_params
|
24
|
+
filtered_params = self.class.discovered_host_params_filter.filter_params(params, parameter_filter_context)
|
25
|
+
process_deprecated_puppet_params!(filtered_params) if defined?(ForemanPuppet)
|
26
|
+
filtered_params
|
27
|
+
end
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
def discovered_host_params_host
|
30
|
+
filtered_params = self.class.discovered_host_params_filter.filter_params(params, parameter_filter_context, :host)
|
31
|
+
process_deprecated_puppet_params!(filtered_params) if defined?(ForemanPuppet)
|
32
|
+
filtered_params
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
def managed_host_params_host
|
36
|
+
filtered_params = self.class.host_params_filter.filter_params(params, parameter_filter_context, :host)
|
37
|
+
process_deprecated_puppet_params!(filtered_params) if defined?(ForemanPuppet)
|
38
|
+
filtered_params
|
39
|
+
end
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
def managed_host_params
|
42
|
+
filtered_params = self.class.host_params_filter.filter_params(params, parameter_filter_context)
|
43
|
+
process_deprecated_puppet_params!(filtered_params) if defined?(ForemanPuppet)
|
44
|
+
filtered_params
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
42
48
|
end
|
43
49
|
end
|
@@ -1,17 +1,23 @@
|
|
1
|
-
module Foreman
|
2
|
-
|
3
|
-
|
1
|
+
module Foreman
|
2
|
+
module Controller
|
3
|
+
module Parameters
|
4
|
+
module DiscoveryRule
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Foreman::Controller::Parameters::Taxonomix
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
class_methods do
|
9
|
+
def discovery_rule_params_filter
|
10
|
+
Foreman::ParameterFilter.new(::DiscoveryRule).tap do |filter|
|
11
|
+
filter.permit :name, :search, :hostname, :priority, :enabled, :hostgroup, :hostgroup_id, :max_count
|
12
|
+
add_taxonomix_params_filter(filter)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def discovery_rule_params
|
18
|
+
self.class.discovery_rule_params_filter.filter_params(params, parameter_filter_context)
|
19
|
+
end
|
10
20
|
end
|
11
21
|
end
|
12
22
|
end
|
13
|
-
|
14
|
-
def discovery_rule_params
|
15
|
-
self.class.discovery_rule_params_filter.filter_params(params, parameter_filter_context)
|
16
|
-
end
|
17
23
|
end
|
@@ -335,19 +335,6 @@ class DiscoveredHostsController < ::ApplicationController
|
|
335
335
|
Bullet.enable = true if defined? Bullet
|
336
336
|
end
|
337
337
|
|
338
|
-
def get_interfaces
|
339
|
-
@host.interfaces.each do |interface|
|
340
|
-
@interfaces << {:identifier => interface["identifier"], :type => interface["type"], :mac => interface["mac"], :ip => interface["ip"]? interface["ip"] : "N/A", :primary => interface["primary"], :provision => interface["provision"]}
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
def add_custom_facts
|
345
|
-
unless @host.primary_interface.subnet.nil?
|
346
|
-
discovery_subnet = "#{@host.primary_interface.subnet.name} (#{@host.primary_interface.subnet.network})"
|
347
|
-
assign_fact_to_category("discovery_subnet", discovery_subnet)
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
338
|
def process_warning(hash = {})
|
352
339
|
warning hash[:warning_msg]
|
353
340
|
end
|
@@ -0,0 +1,354 @@
|
|
1
|
+
class DiscoveredHostsController < ::ApplicationController
|
2
|
+
include Foreman::Controller::Parameters::DiscoveredHost
|
3
|
+
include Foreman::Controller::AutoCompleteSearch
|
4
|
+
include Foreman::Controller::TaxonomyMultiple
|
5
|
+
include Foreman::Controller::DiscoveredExtensions
|
6
|
+
include ActionView::Helpers::NumberHelper
|
7
|
+
|
8
|
+
before_action :find_by_name, :only => %w[edit update destroy refresh_facts convert reboot auto_provision]
|
9
|
+
before_action :find_by_name_incl_subnet, :only => [:show]
|
10
|
+
before_action :find_multiple, :only => [:multiple_destroy, :submit_multiple_destroy, :multiple_reboot, :submit_multiple_reboot, :multiple_auto_provision, :submit_multiple_auto_provision]
|
11
|
+
before_action :taxonomy_scope, :only => [:edit]
|
12
|
+
before_action :check_for_subnet, :only => [:reboot, :auto_provision, :submit_multiple_reboot, :submit_multiple_auto_provision]
|
13
|
+
|
14
|
+
around_action :skip_bullet, :only => [:edit]
|
15
|
+
|
16
|
+
helper :hosts
|
17
|
+
if defined?(ForemanPuppet)
|
18
|
+
helper ForemanPuppet::HostsHelper
|
19
|
+
helper ForemanPuppet::HostsAndHostgroupsHelper
|
20
|
+
helper ForemanPuppet::PuppetclassesHelper
|
21
|
+
helper ForemanPuppet::PuppetclassLookupKeysHelper
|
22
|
+
end
|
23
|
+
|
24
|
+
layout 'layouts/application'
|
25
|
+
|
26
|
+
def model_of_controller
|
27
|
+
Host::Discovered
|
28
|
+
end
|
29
|
+
|
30
|
+
def index
|
31
|
+
@hosts = resource_base_search_and_page.includes([
|
32
|
+
:location,
|
33
|
+
:organization,
|
34
|
+
:model,
|
35
|
+
:discovery_attribute_set
|
36
|
+
], {:interfaces => :subnet})
|
37
|
+
fact_array = @hosts.collect do |host|
|
38
|
+
[host.id, Hash[host.fact_values.joins(:fact_name).where('fact_names.name' => Setting['discovery_fact_column']).pluck(:name, :value)]]
|
39
|
+
end
|
40
|
+
@host_facts = Hash[fact_array]
|
41
|
+
end
|
42
|
+
|
43
|
+
def show
|
44
|
+
# filter graph time range
|
45
|
+
@range = nil
|
46
|
+
# summary report text
|
47
|
+
@report_summary = nil
|
48
|
+
resolver = ForemanDiscovery::FactToCategoryResolver.new(@host)
|
49
|
+
@categories_names = ForemanDiscovery::FactToCategoryResolver::CATEGORIES_NAMES
|
50
|
+
@categories = resolver.categories
|
51
|
+
@interfaces = resolver.interfaces
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy
|
55
|
+
@host.destroy
|
56
|
+
redirect_to :action => 'index'
|
57
|
+
end
|
58
|
+
|
59
|
+
def edit
|
60
|
+
quick = params.delete(:quick_submit)
|
61
|
+
@host = ::ForemanDiscovery::HostConverter.to_managed(@host, true, false, discovered_host_params_host) unless @host.nil?
|
62
|
+
setup_host_class_variables
|
63
|
+
@override_taxonomy = true
|
64
|
+
# need to permit this one but don't know how
|
65
|
+
if quick
|
66
|
+
perform_update(@host, _('Successfully provisioned %s') % @host.name)
|
67
|
+
else
|
68
|
+
@host.build = true
|
69
|
+
render :template => 'discovered_hosts/edit'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def update
|
74
|
+
@host = ::ForemanDiscovery::HostConverter.to_managed(@host, true, true, managed_host_params_host)
|
75
|
+
forward_url_options
|
76
|
+
|
77
|
+
@override_taxonomy = true
|
78
|
+
perform_update(@host)
|
79
|
+
end
|
80
|
+
|
81
|
+
def perform_update(host, success_message = nil)
|
82
|
+
Taxonomy.no_taxonomy_scope do
|
83
|
+
::ForemanDiscovery::HostConverter.set_build_clean_facts(host)
|
84
|
+
::ForemanDiscovery::HostConverter.unused_ip_for_host(host)
|
85
|
+
if host.save
|
86
|
+
host_path = Setting['host_details_ui'] ? host_details_page_path(host) : host_path(host)
|
87
|
+
success_options = { :success_redirect => host_path, :redirect_xhr => request.xhr? }
|
88
|
+
success_options[:success_msg] = success_message if success_message
|
89
|
+
process_success success_options
|
90
|
+
else
|
91
|
+
taxonomy_scope
|
92
|
+
load_vars_for_ajax
|
93
|
+
offer_to_overwrite_conflicts
|
94
|
+
process_error :object => host, :render => 'discovered_hosts/edit'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def refresh_facts
|
100
|
+
if @host.is_a?(::Host::Discovered) && @host.refresh_facts
|
101
|
+
process_success :success_msg => _("Facts refreshed for %s") % @host.name, :success_redirect => :back
|
102
|
+
else
|
103
|
+
process_error :error_msg => _("Failed to refresh facts for %s") % @host.name, :redirect => :back
|
104
|
+
end
|
105
|
+
rescue => e
|
106
|
+
exception = Foreman::WrappedException.new(e, N_("Failed to refresh facts for %{hostname} with error %{error_message}"), :hostname => @host.name, :error_message => e.message)
|
107
|
+
Foreman::Logging.exception exception.message, e
|
108
|
+
process_error :error_msg => exception.message, :redirect => :back
|
109
|
+
end
|
110
|
+
|
111
|
+
def reboot
|
112
|
+
unless @host.is_a?(::Host::Discovered)
|
113
|
+
process_error :error_msg => _("Host of type %s can not be rebooted") % @host.type, :redirect => :back
|
114
|
+
end
|
115
|
+
|
116
|
+
if @host.reboot
|
117
|
+
process_success :success_msg => _("Rebooting host %s") % @host.name, :success_redirect => :back
|
118
|
+
else
|
119
|
+
process_error :error_msg => _("Failed to reboot host %s") % @host.name, :redirect => :back
|
120
|
+
end
|
121
|
+
rescue => e
|
122
|
+
exception = Foreman::WrappedException.new(e, N_("Failed to reboot host %{hostname} with error %{error_message}"), :hostname => @host.name, :error_message => e.message)
|
123
|
+
Foreman::Logging.exception exception.message, e
|
124
|
+
process_error :error_msg => exception.message, :redirect => :back
|
125
|
+
end
|
126
|
+
|
127
|
+
def submit_multiple_reboot
|
128
|
+
error_message = perform_reboot_all(@hosts)
|
129
|
+
|
130
|
+
if error_message
|
131
|
+
process_error :error_msg => error_message, :redirect => :back
|
132
|
+
else
|
133
|
+
process_success :success_msg => _("Discovered hosts are rebooting now"), :success_redirect => :back
|
134
|
+
end
|
135
|
+
rescue => e
|
136
|
+
exception = Foreman::WrappedException.new(e, N_("Failed to reboot hosts with error %s"), e.message)
|
137
|
+
Foreman::Logging.exception exception.message, e
|
138
|
+
process_error :error_msg => exception.message, :redirect => :back
|
139
|
+
end
|
140
|
+
|
141
|
+
def multiple_destroy
|
142
|
+
end
|
143
|
+
|
144
|
+
def multiple_reboot
|
145
|
+
end
|
146
|
+
|
147
|
+
def multiple_auto_provision
|
148
|
+
end
|
149
|
+
|
150
|
+
def submit_multiple_destroy
|
151
|
+
# keep all the ones that were not deleted for notification.
|
152
|
+
missed_hosts = @hosts.select {|host| !host.destroy }
|
153
|
+
if missed_hosts
|
154
|
+
success _("Destroyed selected hosts")
|
155
|
+
else
|
156
|
+
error _("The following hosts were not deleted: %s") % missed_hosts
|
157
|
+
end
|
158
|
+
redirect_to(discovered_hosts_path)
|
159
|
+
end
|
160
|
+
|
161
|
+
def auto_provision
|
162
|
+
if rule = find_discovery_rule(@host)
|
163
|
+
if perform_auto_provision(@host, rule)
|
164
|
+
process_success :success_msg => _("Host %{host} was provisioned with rule %{rule}") % {:host => @host.name, :rule => rule.name}, :success_redirect => discovered_hosts_path
|
165
|
+
else
|
166
|
+
errors = @host.errors.full_messages.join(' ')
|
167
|
+
logger.warn "Failed to auto provision host %s: %s" % [@host.name, errors]
|
168
|
+
process_error :error_msg => _("Failed to auto provision host %s: %s") % [@host.name, errors], :redirect => :back
|
169
|
+
end
|
170
|
+
else
|
171
|
+
process_success :success_msg => _("No rule found for host %s") % @host.name, :success_redirect => :back
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def submit_multiple_auto_provision
|
176
|
+
result = true
|
177
|
+
error_message = _("Errors during auto provisioning: %s")
|
178
|
+
|
179
|
+
if Host::Discovered.count == 0
|
180
|
+
error_message = _("No discovered hosts to provision")
|
181
|
+
result = false
|
182
|
+
end
|
183
|
+
|
184
|
+
overall_errors = ""
|
185
|
+
@hosts.each do |discovered_host|
|
186
|
+
if rule = find_discovery_rule(discovered_host)
|
187
|
+
result &= perform_auto_provision(discovered_host, rule)
|
188
|
+
unless discovered_host.errors.empty?
|
189
|
+
errors = discovered_host.errors.full_messages.join(' ')
|
190
|
+
logger.warn "Failed to auto provision host %s: %s" % [discovered_host.name, errors]
|
191
|
+
overall_errors << "#{discovered_host.name}: #{errors} "
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
if result
|
196
|
+
process_success :success_msg => _("Discovered hosts are provisioning now"), :success_redirect => :back
|
197
|
+
else
|
198
|
+
process_error :error_msg => error_message % overall_errors, :redirect => :back
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def resource_class
|
203
|
+
Host::Discovered
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
def setup_host_class_variables
|
209
|
+
if @host.hostgroup
|
210
|
+
subnet = @host.hostgroup.subnet || @host.subnet
|
211
|
+
subnet6 = @host.hostgroup.subnet6 || @host.subnet6
|
212
|
+
@architecture = @host.hostgroup.architecture
|
213
|
+
@operatingsystem = @host.hostgroup.operatingsystem
|
214
|
+
if defined?(ForemanPuppet)
|
215
|
+
@environment = @host.hostgroup.environment
|
216
|
+
@host.environment = @environment
|
217
|
+
end
|
218
|
+
@domain = @host.hostgroup.domain
|
219
|
+
@subnet = subnet
|
220
|
+
@subnet6 = subnet6
|
221
|
+
@compute_profile = @host.hostgroup.compute_profile
|
222
|
+
@realm = @host.hostgroup.realm
|
223
|
+
@host.interfaces.first.assign_attributes(subnet: subnet, subnet6: subnet6, domain: @domain)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def resource_base
|
228
|
+
@resource_base ||= ::Host::Discovered.authorized(current_permission, ::Host::Discovered)
|
229
|
+
end
|
230
|
+
|
231
|
+
def load_vars_for_ajax
|
232
|
+
return unless @host
|
233
|
+
if defined?(ForemanPuppet)
|
234
|
+
@environment = @host.environment
|
235
|
+
end
|
236
|
+
@architecture = @host.architecture
|
237
|
+
@domain = @host.domain
|
238
|
+
@operatingsystem = @host.operatingsystem
|
239
|
+
@medium = @host.medium
|
240
|
+
end
|
241
|
+
|
242
|
+
# this is required for template generation (such as pxelinux) which is not done via a web request
|
243
|
+
def forward_url_options(host = @host)
|
244
|
+
host.url_options = url_options if @host.respond_to?(:url_options)
|
245
|
+
end
|
246
|
+
|
247
|
+
# if a save failed and the only reason was network conflicts then flag this so that the view
|
248
|
+
# is rendered differently and the next save operation will be forced
|
249
|
+
def offer_to_overwrite_conflicts
|
250
|
+
@host.overwrite = "true" if @host.errors.any? and @host.errors.are_all_conflicts?
|
251
|
+
end
|
252
|
+
|
253
|
+
def controller_permission
|
254
|
+
'discovered_hosts'
|
255
|
+
end
|
256
|
+
|
257
|
+
def action_permission
|
258
|
+
case params[:action]
|
259
|
+
when 'refresh_facts', 'reboot', 'multiple_reboot', 'update_multiple_location',
|
260
|
+
'select_multiple_organization', 'update_multiple_organization', 'select_multiple_location', 'submit_multiple_reboot'
|
261
|
+
:edit
|
262
|
+
when 'submit_multiple_destroy', 'multiple_destroy'
|
263
|
+
:destroy
|
264
|
+
when 'auto_provision', 'multiple_auto_provision', 'submit_multiple_auto_provision'
|
265
|
+
:auto_provision
|
266
|
+
else
|
267
|
+
super
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def find_by_name(*includes)
|
272
|
+
not_found and return false if (id = params[:id]).blank?
|
273
|
+
id.downcase!
|
274
|
+
@host = includes.empty? ? resource_base.find_by_id(id) : resource_base.includes(includes).find_by_id(id)
|
275
|
+
@host ||= includes.empty? ? resource_base.find_by_name(id) : resource_base.includes(includes).find_by_name(id)
|
276
|
+
not_found and return(false) unless @host
|
277
|
+
@host
|
278
|
+
end
|
279
|
+
|
280
|
+
def check_for_subnet
|
281
|
+
hosts_without_subnet = []
|
282
|
+
case params[:action]
|
283
|
+
when 'reboot', 'auto_provision'
|
284
|
+
if @host.subnet.nil?
|
285
|
+
process_warning :warning_msg => _("Discovered host reported from unknown subnet, communication will not be proxied.")
|
286
|
+
end
|
287
|
+
when 'submit_multiple_reboot', 'submit_multiple_auto_provision'
|
288
|
+
hosts_without_subnet = @hosts.limit(3).select { |host| host.subnet.nil? }.pluck(:name)
|
289
|
+
if hosts_without_subnet.present?
|
290
|
+
process_warning :warning_msg => _("Discovered hosts reported from unknown subnet are %s, communication will not be proxied.") % hosts_without_subnet.join(', ')
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def find_by_name_incl_subnet
|
296
|
+
find_by_name({:interfaces => :subnet})
|
297
|
+
end
|
298
|
+
|
299
|
+
def find_multiple
|
300
|
+
# Lets search by name or id and make sure one of them exists first
|
301
|
+
if params[:host_names].present? or params[:host_ids].present?
|
302
|
+
@hosts = Host::Discovered.includes(:model, :fact_values, :interfaces, :location, :organization).where("id IN (?) or name IN (?)", params[:host_ids], params[:host_names] )
|
303
|
+
if @hosts.empty?
|
304
|
+
error _('No hosts were found with that id or name')
|
305
|
+
redirect_to(discovered_hosts_path) and return false
|
306
|
+
end
|
307
|
+
else
|
308
|
+
error _('No hosts selected')
|
309
|
+
redirect_to(discovered_hosts_path) and return false
|
310
|
+
end
|
311
|
+
|
312
|
+
return @hosts
|
313
|
+
rescue => e
|
314
|
+
error _("Something went wrong while selecting hosts - %s") % e
|
315
|
+
redirect_to discovered_hosts_path
|
316
|
+
end
|
317
|
+
|
318
|
+
def taxonomy_scope
|
319
|
+
if @host
|
320
|
+
@organization = @host.organization
|
321
|
+
@location = @host.location
|
322
|
+
end
|
323
|
+
|
324
|
+
@organization ||= Organization.current
|
325
|
+
@organization ||= Organization.my_organizations.first
|
326
|
+
@location ||= Location.current
|
327
|
+
@location ||= Location.my_locations.first
|
328
|
+
end
|
329
|
+
|
330
|
+
# particular actions will always raise N+1 queries
|
331
|
+
def skip_bullet
|
332
|
+
Bullet.enable = false if defined? Bullet
|
333
|
+
yield
|
334
|
+
ensure
|
335
|
+
Bullet.enable = true if defined? Bullet
|
336
|
+
end
|
337
|
+
|
338
|
+
<<<<<<< HEAD
|
339
|
+
def add_custom_facts
|
340
|
+
unless @host.primary_interface.subnet.nil?
|
341
|
+
discovery_subnet = "#{@host.primary_interface.subnet.name} (#{@host.primary_interface.subnet.network})"
|
342
|
+
assign_fact_to_category("discovery_subnet", discovery_subnet)
|
343
|
+
=======
|
344
|
+
def get_interfaces
|
345
|
+
@host.interfaces.each do |interface|
|
346
|
+
@interfaces << {:identifier => interface["identifier"], :type => interface["type"], :mac => interface["mac"], :ip => interface["ip"]? interface["ip"] : "N/A", :primary => interface["primary"], :provision => interface["provision"]}
|
347
|
+
>>>>>>> 58baad5 (Support subnet6 facts in FactToCategoryResolver)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def process_warning(hash = {})
|
352
|
+
warning hash[:warning_msg]
|
353
|
+
end
|
354
|
+
end
|
@@ -18,6 +18,7 @@ class Host::Discovered < ::Host::Base
|
|
18
18
|
scoped_search :on => :created_at, :default_order => :desc, :only_explicit => true
|
19
19
|
scoped_search :on => :last_report, :complete_value => true, :only_explicit => true
|
20
20
|
scoped_search :relation => :primary_interface, :on => :ip, :complete_value => true
|
21
|
+
scoped_search :relation => :primary_interface, :on => :ip6, :complete_value => true
|
21
22
|
scoped_search :relation => :primary_interface, :on => :mac, :complete_value => true
|
22
23
|
scoped_search :relation => :model, :on => :name, :complete_value => true, :rename => :model, :only_explicit => true
|
23
24
|
scoped_search :relation => :fact_values, :on => :value, :in_key => :fact_names, :on_key => :name, :rename => :facts, :complete_value => true, :only_explicit => true
|
@@ -33,7 +33,8 @@ module ForemanDiscovery
|
|
33
33
|
identifier: interface["identifier"],
|
34
34
|
type: interface["type"],
|
35
35
|
mac: interface["mac"],
|
36
|
-
ip: interface["ip"]
|
36
|
+
ip: interface["ip"],
|
37
|
+
ip6: interface["ip6"],
|
37
38
|
primary: interface["primary"],
|
38
39
|
provision: interface["provision"],
|
39
40
|
}
|
@@ -50,10 +51,7 @@ module ForemanDiscovery
|
|
50
51
|
assign_fact_to_category(key, value)
|
51
52
|
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
discovery_subnet = "#{host.primary_interface.subnet.name} (#{host.primary_interface.subnet.network})"
|
56
|
-
assign_fact_to_category("discovery_subnet", discovery_subnet)
|
54
|
+
subnets_facts(host.primary_interface)
|
57
55
|
end
|
58
56
|
|
59
57
|
def assign_fact_to_category(key, value)
|
@@ -74,6 +72,14 @@ module ForemanDiscovery
|
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
75
|
+
def subnets_facts(iface)
|
76
|
+
subnet4 = iface.subnet
|
77
|
+
subnet6 = iface.subnet6
|
78
|
+
|
79
|
+
assign_fact_to_category("discovery_subnet", "#{subnet4.name} (#{subnet4.network})") if subnet4
|
80
|
+
assign_fact_to_category("discovery_subnet6", "#{subnet6.name} (#{subnet6.network})") if subnet6
|
81
|
+
end
|
82
|
+
|
77
83
|
def highlights
|
78
84
|
/^(productname|memorysize|manufacturer|architecture|macaddress$|processorcount|physicalprocessorcount|discovery_subnet|discovery_boot|ipaddress$)/
|
79
85
|
end
|
@@ -103,4 +109,3 @@ module ForemanDiscovery
|
|
103
109
|
end
|
104
110
|
end
|
105
111
|
end
|
106
|
-
|
@@ -52,15 +52,18 @@ module ForemanDiscovery
|
|
52
52
|
|
53
53
|
return if neighbors.nil?
|
54
54
|
|
55
|
-
ip
|
55
|
+
ip = primary.ip
|
56
|
+
ip6 = primary.ip6
|
56
57
|
mac = primary.mac
|
57
58
|
name = primary.name
|
59
|
+
|
58
60
|
primary.update(
|
59
61
|
:primary => false,
|
60
62
|
:provision => false,
|
61
63
|
:managed => false,
|
62
64
|
:name => nil,
|
63
|
-
:ip => nil
|
65
|
+
:ip => nil,
|
66
|
+
:ip6 => nil
|
64
67
|
)
|
65
68
|
|
66
69
|
bond = Nic::Bond.create(
|
@@ -70,6 +73,7 @@ module ForemanDiscovery
|
|
70
73
|
:provision => true,
|
71
74
|
:name => name,
|
72
75
|
:ip => ip,
|
76
|
+
:ip6 => ip6,
|
73
77
|
:mac => mac,
|
74
78
|
:host => host
|
75
79
|
)
|
@@ -2,7 +2,8 @@ object @discovered_host
|
|
2
2
|
|
3
3
|
extends "api/v2/discovered_hosts/base"
|
4
4
|
|
5
|
-
attributes :ip, :mac, :last_report, :subnet_id,
|
5
|
+
attributes :ip, :ip6, :mac, :last_report, :subnet_id,
|
6
|
+
:subnet_name, :hardware_model_name, :memory, :disk_count, :disks_size
|
6
7
|
attribute :cpu_count => :cpus
|
7
8
|
|
8
9
|
node :subnet_name do |host|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<td class="ellipsis"><%= link_to (discovery_status_icon(host) + ' '.html_safe + trunc_with_tooltip(h(host.name))), discovered_host_path(host) %></td>
|
2
2
|
<td class="hidden-tablet hidden-xs"><%= host.try(:hardware_model_name) || 'N/A' %></td>
|
3
3
|
<td class="hidden-tablet hidden-xs"><%= host.ip %></td>
|
4
|
+
<td class="hidden-tablet hidden-xs"><%= host.ip6 %></td>
|
4
5
|
<td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :cpu_count) %></td>
|
5
6
|
<td class="hidden-tablet hidden-xs"><%= number_to_human_size(discovery_attribute(host, :memory, 0) * 1024 * 1024) %></td>
|
6
7
|
<td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :disk_count) %></td>
|
@@ -5,7 +5,8 @@
|
|
5
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
6
|
<th class=''><%= sort :name, :as => _('Name') %></th>
|
7
7
|
<th class="hidden-tablet hidden-xs"><%= sort :model, :as => _('Model') %></th>
|
8
|
-
<th class="hidden-tablet hidden-xs"><%= sort :ip, :as => _('
|
8
|
+
<th class="hidden-tablet hidden-xs"><%= sort :ip, :as => _('IPv4') %></th>
|
9
|
+
<th class="hidden-tablet hidden-xs"><%= sort :ip6, :as => _('IPv6') %></th>
|
9
10
|
<th class="hidden-tablet hidden-xs"><%= sort :cpu_count, :as => _('CPUs') %></th>
|
10
11
|
<th class="hidden-tablet hidden-xs"><%= sort :memory, :as => _('Memory') %></th>
|
11
12
|
<th class="hidden-tablet hidden-xs"><%= sort :disk_count, :as => _('Disk Count') %></th>
|
@@ -44,7 +44,8 @@
|
|
44
44
|
<th class="hidden-xs " width="12%"><%= _('Type') %></th>
|
45
45
|
<th class="hidden-xs "><%= _('Identifier') %></th>
|
46
46
|
<th class="hidden-xs "><%= _("MAC address") %></th>
|
47
|
-
<th class="hidden-xs "><%= _("
|
47
|
+
<th class="hidden-xs "><%= _("IPv4") %></th>
|
48
|
+
<th class="hidden-xs "><%= _("IPv6") %></th>
|
48
49
|
</tr>
|
49
50
|
<% @interfaces.each do |interface| %>
|
50
51
|
<tr>
|
@@ -52,6 +53,7 @@
|
|
52
53
|
<td class="ellipsis"><%= interface[:identifier] %></td>
|
53
54
|
<td class="ellipsis"><%= interface[:mac] %></td>
|
54
55
|
<td class="ellipsis"><%= interface[:ip] %></td>
|
56
|
+
<td class="ellipsis"><%= interface[:ip6] %></td>
|
55
57
|
</tr>
|
56
58
|
<% end %>
|
57
59
|
</table>
|
@@ -3,7 +3,12 @@
|
|
3
3
|
<%= link_to host, discovered_host_url(:id => host, :host => @url.host, :port => @url.port, :only_path => false, :protocol => @url.scheme) %>
|
4
4
|
</td>
|
5
5
|
<td style="<%= td_style%>"><%= host.try(:hardware_model_name) || 'N/A' %></td>
|
6
|
+
<% if host.ip %>
|
6
7
|
<td style="<%= td_style%>"><%= host.ip %></td>
|
8
|
+
<% end %>
|
9
|
+
<% if host.ip6 %>
|
10
|
+
<td style="<%= td_style%>"><%= host.ip6 %></td>
|
11
|
+
<% end %>
|
7
12
|
<td style="<%= td_style%>"><%= discovery_attribute(host, :cpu_count) %></td>
|
8
13
|
<td style="<%= td_style%>"><%= number_to_human_size(discovery_attribute(host, :memory, 0) * 1024 * 1024) %></td>
|
9
14
|
<td style="<%= td_style%>"><%= discovery_attribute(host, :disk_count) %></td>
|
@@ -44,7 +44,9 @@
|
|
44
44
|
"timezone": "GMT",
|
45
45
|
"fqdn": "a.server.b.domain",
|
46
46
|
"ipaddress_eth0": "10.35.27.3",
|
47
|
+
"ipaddress6_eth0": "2001:db8:9a7b:fb60::3",
|
47
48
|
"ipaddress_eth1": "10.35.27.4",
|
49
|
+
"ipaddress6_eth1": "2001:db8:9a7b:fb60::4",
|
48
50
|
"puppetversion": "2.6.12",
|
49
51
|
"path": "/root/.gem/bin:/root/.gem/ruby/1.8/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/sbin:/usr/sbin:/root/scripts",
|
50
52
|
"hardwaremodel": "x86_64",
|
@@ -58,11 +60,14 @@
|
|
58
60
|
"macaddress_eth0_182": "E4:1F:13:CC:36:58",
|
59
61
|
"memorysize": "15.57 GB",
|
60
62
|
"ipaddress": "10.35.27.2",
|
63
|
+
"ipaddress6": "2001:db8:5f42:7cd1::2",
|
61
64
|
"rubyversion": "1.8.7",
|
62
65
|
"macaddress_eth0_183": "E4:1F:13:CC:36:58",
|
63
66
|
"physicalprocessorcount": "1",
|
64
67
|
"network_lo": "127.0.0.0",
|
68
|
+
"network6_lo": "::1",
|
65
69
|
"gateway": "10.35.27.62",
|
70
|
+
"gateway6": "2001:db8:2c7d:f15e::3e",
|
66
71
|
"lsbdistid": "RedHatEnterpriseServer",
|
67
72
|
"lsbdistdescription": "Red Hat Enterprise Linux Server release 6.2 (Santiago)",
|
68
73
|
"swapsize": "17.70 GB",
|
@@ -90,11 +95,13 @@
|
|
90
95
|
"lldp_neighbor_portID_eth1": "Eth170/1/3",
|
91
96
|
"lldp_neighbor_sysName_eth1": "DC2-A03-DR-01",
|
92
97
|
"lldp_neighbor_mngAddr_ipv4_eth1": "192.0.2.13",
|
98
|
+
"lldp_neighbor_mngAddr_ipv6_eth1": "2001:db8:4d2b:dc7b::13",
|
93
99
|
"lldp_neighbor_PVID_eth1": "182",
|
94
100
|
"lldp_neighbor_chassisID_eth0": "e0:d1:73:38:5a:84",
|
95
101
|
"lldp_neighbor_portID_eth0": "Eth171/1/3",
|
96
102
|
"lldp_neighbor_sysName_eth0": "DC2-A04-DR-03",
|
97
103
|
"lldp_neighbor_mngAddr_ipv4_eth0": "192.0.2.13",
|
104
|
+
"lldp_neighbor_mngAddr_ipv6_eth0": "2001:db8:4d2b:dc7b::13",
|
98
105
|
"lldp_neighbor_PVID_eth0": "182"
|
99
106
|
}
|
100
107
|
}
|
@@ -25,6 +25,12 @@ class Api::V2::DiscoveredHostsControllerTest < ActionController::TestCase
|
|
25
25
|
"memorysize_mb" => "42000.42",
|
26
26
|
"discovery_version" => "3.0.0",
|
27
27
|
}
|
28
|
+
|
29
|
+
@facts6 = @facts.merge({
|
30
|
+
"ipaddress" => "2001:db8::1",
|
31
|
+
"ipaddress6_eth0" => "2001:db8::1",
|
32
|
+
})
|
33
|
+
|
28
34
|
set_default_settings
|
29
35
|
::ForemanDiscovery::NodeAPI::PowerService.any_instance.stubs(:reboot).returns(true)
|
30
36
|
::ForemanDiscovery::HostConverter.stubs(:unused_ip_for_host)
|
@@ -52,6 +58,16 @@ class Api::V2::DiscoveredHostsControllerTest < ActionController::TestCase
|
|
52
58
|
assert_equal Setting[:discovery_location], show_response["location_name"]
|
53
59
|
end
|
54
60
|
|
61
|
+
def test_show_host_ipv6
|
62
|
+
host = discover_host_from_facts(@facts6)
|
63
|
+
get :show, params: { :id => host.id }
|
64
|
+
assert_response :success
|
65
|
+
|
66
|
+
response = ActiveSupport::JSON.decode(@response.body)
|
67
|
+
assert_equal "macaabbccddeeff", response["name"]
|
68
|
+
assert_equal @facts6["ipaddress6_eth0"], response["ip6"]
|
69
|
+
end
|
70
|
+
|
55
71
|
def test_delete_discovered_host
|
56
72
|
host = discover_host_from_facts(@facts)
|
57
73
|
delete :destroy, params: { :id => host.id }
|
@@ -91,6 +107,25 @@ class Api::V2::DiscoveredHostsControllerTest < ActionController::TestCase
|
|
91
107
|
assert actual.build?
|
92
108
|
end
|
93
109
|
|
110
|
+
def test_provision_ipv6_host
|
111
|
+
subnet6 = FactoryBot.create(:subnet_ipv6, :network => "2001:db8::")
|
112
|
+
host = discover_host_from_facts(@facts6)
|
113
|
+
hostgroup = setup_hostgroup(host, subnets: { subnet6: subnet6 })
|
114
|
+
|
115
|
+
put :update, params: {
|
116
|
+
id: host.id,
|
117
|
+
discovered_host: {
|
118
|
+
hostgroup_id: hostgroup.id,
|
119
|
+
build: true
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
assert_response :success
|
124
|
+
actual = Host.unscoped.find(host.id)
|
125
|
+
assert actual.build?
|
126
|
+
assert_equal actual.ip6, @facts6["ipaddress6_eth0"]
|
127
|
+
end
|
128
|
+
|
94
129
|
def test_provision_host_without_build_flag
|
95
130
|
FactoryBot.create(:organization, :name => 'SomeOrg')
|
96
131
|
FactoryBot.create(:location, :name => 'SomeLoc')
|
@@ -70,9 +70,11 @@ def set_default_settings
|
|
70
70
|
Setting['discovery_auto_bond'] = false
|
71
71
|
end
|
72
72
|
|
73
|
-
def setup_hostgroup(host)
|
73
|
+
def setup_hostgroup(host, subnets: nil)
|
74
74
|
domain = FactoryBot.create(:domain)
|
75
|
-
|
75
|
+
subnets ||= {
|
76
|
+
subnet: FactoryBot.create(:subnet_ipv4, :network => "192.168.100.0")
|
77
|
+
}
|
76
78
|
medium = FactoryBot.create(:medium, :organizations => [host.organization], :locations => [host.location])
|
77
79
|
os = FactoryBot.create(:operatingsystem, :with_ptables, :with_archs, :media => [medium])
|
78
80
|
args = {
|
@@ -80,11 +82,11 @@ def setup_hostgroup(host)
|
|
80
82
|
:architecture => os.architectures.first,
|
81
83
|
:ptable => os.ptables.first,
|
82
84
|
:medium => os.media.first,
|
83
|
-
:subnet => subnet,
|
84
85
|
:domain => domain,
|
85
86
|
:organizations => [host.organization],
|
86
87
|
:locations => [host.location]
|
87
|
-
}
|
88
|
+
}.merge(subnets)
|
89
|
+
|
88
90
|
if defined?(ForemanPuppet)
|
89
91
|
environment = FactoryBot.create(:environment, :organizations => [host.organization], :locations => [host.location])
|
90
92
|
args[:environment] = environment
|
@@ -92,15 +94,26 @@ def setup_hostgroup(host)
|
|
92
94
|
else
|
93
95
|
hostgroup = FactoryBot.create(:hostgroup, :with_rootpass, **args)
|
94
96
|
end
|
95
|
-
|
97
|
+
|
98
|
+
hostgroup_subnets = [hostgroup.subnet6, hostgroup.subnet].compact
|
99
|
+
domain.subnets << hostgroup_subnets
|
100
|
+
|
101
|
+
hostgroup_taxonomies(hostgroup, hostgroup_subnets, host)
|
102
|
+
end
|
103
|
+
|
104
|
+
def hostgroup_taxonomies(hostgroup, hostgroup_subnets, host)
|
96
105
|
hostgroup.medium.organizations |= [host.organization]
|
97
106
|
hostgroup.medium.locations |= [host.location]
|
98
107
|
hostgroup.ptable.organizations |= [host.organization]
|
99
108
|
hostgroup.ptable.locations |= [host.location]
|
100
109
|
hostgroup.domain.organizations |= [host.organization]
|
101
110
|
hostgroup.domain.locations |= [host.location]
|
102
|
-
|
103
|
-
|
111
|
+
|
112
|
+
hostgroup_subnets.each do |subnet|
|
113
|
+
subnet.organizations |= [host.organization]
|
114
|
+
subnet.locations |= [host.location]
|
115
|
+
end
|
116
|
+
|
104
117
|
if defined?(ForemanPuppet)
|
105
118
|
hostgroup.environment.organizations |= [host.organization]
|
106
119
|
hostgroup.environment.locations |= [host.location]
|
@@ -109,6 +122,7 @@ def setup_hostgroup(host)
|
|
109
122
|
hostgroup.puppet_ca_proxy.organizations |= [host.organization]
|
110
123
|
hostgroup.puppet_ca_proxy.locations |= [host.location]
|
111
124
|
end
|
125
|
+
|
112
126
|
hostgroup
|
113
127
|
end
|
114
128
|
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require_relative '../test_plugin_helper'
|
2
2
|
|
3
3
|
class LldpNeighborsTest < ActiveSupport::TestCase
|
4
|
+
include FactImporterIsolation
|
5
|
+
allow_transactions_for_any_importer
|
6
|
+
|
4
7
|
test "#get_neighbors_by_interface gives nothing with no LLDP facts" do
|
5
8
|
assert_nil simple_facts.get_neighbors_by_interface('eth0')
|
6
9
|
end
|
@@ -32,6 +35,37 @@ class LldpNeighborsTest < ActiveSupport::TestCase
|
|
32
35
|
assert_equal({'182' => %w(eth2), '184' => %w(eth1)}, lldp_facts.list_by_pvid)
|
33
36
|
end
|
34
37
|
|
38
|
+
test "#eventually_make_bond" do
|
39
|
+
facts = parse_json_fixture('facts_with_lldp_bond_candidate', true)
|
40
|
+
host = discover_host_from_facts(facts)
|
41
|
+
primary = host.primary_interface
|
42
|
+
|
43
|
+
assert_equal 0, host.interfaces.where(:type => 'Nic::Bond').count
|
44
|
+
|
45
|
+
assert primary.primary
|
46
|
+
assert primary.provision
|
47
|
+
assert primary.ip
|
48
|
+
assert primary.ip6
|
49
|
+
|
50
|
+
ForemanDiscovery::LldpNeighbors.eventually_make_bond(host)
|
51
|
+
|
52
|
+
bond = host.primary_interface
|
53
|
+
|
54
|
+
assert_nil primary.ip
|
55
|
+
assert_nil primary.ip6
|
56
|
+
assert_nil primary.name
|
57
|
+
assert_not primary.primary
|
58
|
+
assert_not primary.provision
|
59
|
+
assert_not primary.managed
|
60
|
+
|
61
|
+
assert bond.primary
|
62
|
+
assert bond.provision
|
63
|
+
assert bond.ip
|
64
|
+
assert bond.ip6
|
65
|
+
assert_equal bond.type, 'Nic::Bond'
|
66
|
+
assert_equal bond.identifier, 'bond0'
|
67
|
+
end
|
68
|
+
|
35
69
|
private
|
36
70
|
|
37
71
|
def simple_facts
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_discovery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 25.0
|
4
|
+
version: 25.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aditi Puntambekar
|
@@ -76,7 +76,7 @@ authors:
|
|
76
76
|
autorequire:
|
77
77
|
bindir: bin
|
78
78
|
cert_chain: []
|
79
|
-
date:
|
79
|
+
date: 2025-01-27 00:00:00.000000000 Z
|
80
80
|
dependencies: []
|
81
81
|
description: MaaS Discovery Plugin engine for Foreman
|
82
82
|
email: gsutclif@redhat.com
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- app/controllers/concerns/foreman/controller/parameters/discovered_host.rb
|
113
113
|
- app/controllers/concerns/foreman/controller/parameters/discovery_rule.rb
|
114
114
|
- app/controllers/discovered_hosts_controller.rb
|
115
|
+
- app/controllers/discovered_hosts_controller.rb.orig
|
115
116
|
- app/controllers/discovery_rules_controller.rb
|
116
117
|
- app/controllers/foreman_discovery/concerns/hosts_controller_extensions.rb
|
117
118
|
- app/helpers/discovered_hosts_helper.rb
|