foreman_discovery 15.0.1 → 16.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/discovery_rules_controller.rb +1 -1
- data/app/controllers/concerns/foreman/controller/discovered_extensions.rb +4 -0
- data/app/controllers/discovered_hosts_controller.rb +1 -0
- data/app/controllers/discovery_rules_controller.rb +1 -1
- data/app/models/discovery_rule.rb +1 -1
- data/app/models/host/discovered.rb +37 -15
- data/app/models/host/managed_extensions.rb +1 -1
- data/app/models/setting/discovered.rb +26 -33
- data/app/services/foreman_discovery/fact_parser.rb +1 -1
- data/app/services/foreman_discovery/host_converter.rb +30 -2
- data/app/services/foreman_discovery/import_hooks/subnet_and_taxonomy.rb +6 -14
- data/app/services/foreman_discovery/subnet_suggestion.rb +26 -0
- data/app/views/discovered_hosts/_discovered_host_modal.html.erb +19 -17
- data/app/views/foreman_discovery/debian_kexec.erb +1 -1
- data/config/routes.rb +2 -0
- data/db/migrate/20150512150432_remove_old_discovery_reader_permissions.rb +1 -1
- data/db/migrate/20151023144501_regenerate_red_hat_kexec.rb +1 -1
- data/db/migrate/20180412124505_add_priority_score_to_discovery_rules.rb +1 -1
- data/extra/discover-host +21 -7
- data/lib/foreman_discovery/engine.rb +4 -4
- data/lib/foreman_discovery/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ca/foreman_discovery.edit.po +238 -139
- data/locale/ca/foreman_discovery.po +28 -8
- data/locale/de/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/de/foreman_discovery.edit.po +240 -140
- data/locale/de/foreman_discovery.po +31 -11
- data/locale/en/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en/foreman_discovery.edit.po +109 -83
- data/locale/en/foreman_discovery.po +24 -4
- data/locale/en_GB/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/en_GB/foreman_discovery.edit.po +241 -142
- data/locale/en_GB/foreman_discovery.po +31 -11
- data/locale/es/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/es/foreman_discovery.edit.po +240 -141
- data/locale/es/foreman_discovery.po +30 -10
- data/locale/foreman_discovery.pot +110 -84
- data/locale/fr/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/fr/foreman_discovery.edit.po +237 -137
- data/locale/fr/foreman_discovery.po +28 -8
- data/locale/gl/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/gl/foreman_discovery.edit.po +236 -137
- data/locale/gl/foreman_discovery.po +26 -6
- data/locale/it/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/it/foreman_discovery.edit.po +236 -137
- data/locale/it/foreman_discovery.po +26 -6
- data/locale/ja/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ja/foreman_discovery.edit.po +238 -142
- data/locale/ja/foreman_discovery.po +29 -9
- data/locale/ko/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ko/foreman_discovery.edit.po +236 -139
- data/locale/ko/foreman_discovery.po +28 -8
- data/locale/pt_BR/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/pt_BR/foreman_discovery.edit.po +239 -140
- data/locale/pt_BR/foreman_discovery.po +29 -9
- data/locale/ru/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/ru/foreman_discovery.edit.po +242 -143
- data/locale/ru/foreman_discovery.po +29 -9
- data/locale/sv_SE/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/sv_SE/foreman_discovery.edit.po +237 -138
- data/locale/sv_SE/foreman_discovery.po +27 -7
- data/locale/zh_CN/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_CN/foreman_discovery.edit.po +237 -141
- data/locale/zh_CN/foreman_discovery.po +28 -8
- data/locale/zh_TW/LC_MESSAGES/foreman_discovery.mo +0 -0
- data/locale/zh_TW/foreman_discovery.edit.po +235 -139
- data/locale/zh_TW/foreman_discovery.po +26 -6
- data/test/facts/bond0-eth0-eth1-active-passive.json +128 -0
- data/test/facts/facts_with_lldp_bond_candidate.json +2 -9
- data/test/functional/api/v2/discovered_hosts_controller_test.rb +1 -0
- data/test/functional/discovered_hosts_controller_test.rb +4 -4
- data/test/integration/discovered_hosts_test.rb +6 -11
- data/test/test_helper_discovery.rb +12 -0
- data/test/unit/discovered_extensions_test.rb +53 -0
- data/test/unit/discovery_attribute_set_test.rb +13 -10
- data/test/unit/discovery_rule_test.rb +1 -0
- data/test/unit/host_discovered_test.rb +32 -13
- data/test/unit/managed_extensions_test.rb +1 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65c100401474ba94276c5cae8afa8dcf20d7b77b856d20956abc29107c2b5f22
|
4
|
+
data.tar.gz: 54fc5dea8b179f139361e145f312588e5803b8b5eb9ea6a1166e55030acc37c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 474c76e3d67d56849cbf15919d08aead8d845a61ab69d31c8db238d45b49b6ee9ec72ed5ec9044fcb4871509f2ef89333d041e1481243fc7cd6e8f034acf40f3
|
7
|
+
data.tar.gz: 78cb83d2a57281eacc9a339d78bf55607e545b31e77b0106f127aa4d8ae49582df7e6a28170d52eb882300ebb45e09d25b9d7a31b5af084af4da712c6faa6eaf
|
@@ -55,7 +55,7 @@ module Api
|
|
55
55
|
param_group :discovery_rule, :as => :update
|
56
56
|
|
57
57
|
def update
|
58
|
-
process_response @discovery_rule.
|
58
|
+
process_response @discovery_rule.update(discovery_rule_params)
|
59
59
|
end
|
60
60
|
|
61
61
|
api :DELETE, "/discovery_rules/:id/", N_("Delete a rule")
|
@@ -41,6 +41,8 @@ module Foreman::Controller::DiscoveredExtensions
|
|
41
41
|
# trigger the provisioning
|
42
42
|
def perform_auto_provision original_host, rule
|
43
43
|
raise(::Foreman::Exception.new(N_("No hostgroup associated with rule '%s'"), rule)) if rule.hostgroup.nil?
|
44
|
+
|
45
|
+
logger.debug "Auto-provisioning via rule #{rule} hostgroup #{rule.hostgroup} subnet #{rule.hostgroup.subnet}"
|
44
46
|
host = ::ForemanDiscovery::HostConverter.to_managed(original_host)
|
45
47
|
host.hostgroup_id = rule.hostgroup_id
|
46
48
|
host.comment = "Auto-discovered and provisioned via rule '#{rule.name}'"
|
@@ -55,6 +57,8 @@ module Foreman::Controller::DiscoveredExtensions
|
|
55
57
|
# explicitly set all inheritable attributes from hostgroup
|
56
58
|
host.attributes = host.apply_inherited_attributes(hostgroup_id: rule.hostgroup_id)
|
57
59
|
host.set_hostgroup_defaults
|
60
|
+
# change subnet and fetch unused IPs
|
61
|
+
::ForemanDiscovery::HostConverter.unused_ip_for_host(host, rule.hostgroup.subnet, rule.hostgroup.subnet6)
|
58
62
|
# save! does not work here
|
59
63
|
if host.save
|
60
64
|
host
|
@@ -78,6 +78,7 @@ class DiscoveredHostsController < ::ApplicationController
|
|
78
78
|
def perform_update(host, success_message = nil)
|
79
79
|
Taxonomy.no_taxonomy_scope do
|
80
80
|
::ForemanDiscovery::HostConverter.set_build_clean_facts(host)
|
81
|
+
::ForemanDiscovery::HostConverter.unused_ip_for_host(host)
|
81
82
|
if host.save
|
82
83
|
success_options = { :success_redirect => host_path(host), :redirect_xhr => request.xhr? }
|
83
84
|
success_options[:success_msg] = success_message if success_message
|
@@ -22,7 +22,7 @@ class DiscoveryRule < ApplicationRecord
|
|
22
22
|
before_validation :enforce_taxonomy
|
23
23
|
|
24
24
|
belongs_to :hostgroup
|
25
|
-
|
25
|
+
has_many_hosts :dependent => :nullify
|
26
26
|
|
27
27
|
scoped_search :on => :name, :complete_value => :true
|
28
28
|
scoped_search :on => :priority, :only_explicit => true
|
@@ -137,12 +137,12 @@ class Host::Discovered < ::Host::Base
|
|
137
137
|
subnet.present? && subnet.discovery.present?
|
138
138
|
end
|
139
139
|
|
140
|
-
def proxy_url
|
141
|
-
proxied? ? subnet.discovery.url + "/discovery/#{
|
140
|
+
def proxy_url(node_ip)
|
141
|
+
proxied? ? subnet.discovery.url + "/discovery/#{node_ip}" : "https://#{node_ip}:8443"
|
142
142
|
end
|
143
143
|
|
144
144
|
def refresh_facts
|
145
|
-
facts = ::ForemanDiscovery::NodeAPI::Inventory.new(:url => proxy_url).facter
|
145
|
+
facts = ::ForemanDiscovery::NodeAPI::Inventory.new(:url => proxy_url(self.ip)).facter
|
146
146
|
self.class.import_host facts
|
147
147
|
import_facts facts
|
148
148
|
rescue => e
|
@@ -150,20 +150,42 @@ class Host::Discovered < ::Host::Base
|
|
150
150
|
raise ::Foreman::WrappedException.new(e, N_("Could not get facts from proxy %{url}: %{error}"), :url => proxy_url, :error => e)
|
151
151
|
end
|
152
152
|
|
153
|
-
def reboot
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
153
|
+
def reboot(node_ip = nil)
|
154
|
+
# perform the action against the original lease as well as the new reservation
|
155
|
+
[node_ip || facts["discovery_bootip"] || facts["ipaddress"], self.ip].compact.each do |next_ip|
|
156
|
+
begin
|
157
|
+
node_url = proxy_url(next_ip)
|
158
|
+
logger.debug "Performing reboot call against #{node_url}"
|
159
|
+
resource = ::ForemanDiscovery::NodeAPI::Power.service(:url => node_url)
|
160
|
+
return true if resource.reboot
|
161
|
+
rescue => e
|
162
|
+
msg = N_("Unable to perform reboot on %{name} (%{url}): %{msg}")
|
163
|
+
::Foreman::Logging.exception(msg % { :name => name, :url => node_url, :msg => e.to_s }, e)
|
164
|
+
if next_ip == self.ip
|
165
|
+
raise ::Foreman::WrappedException.new(e, msg, :name => name, :url => node_url, :msg => e.to_s)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
false
|
159
170
|
end
|
160
171
|
|
161
|
-
def kexec
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
172
|
+
def kexec(json, node_ip = nil)
|
173
|
+
# perform the action against the original lease as well as the new reservation
|
174
|
+
[node_ip || facts["discovery_bootip"] || facts["ipaddress"], self.ip].compact.each do |next_ip|
|
175
|
+
begin
|
176
|
+
node_url = proxy_url(next_ip)
|
177
|
+
logger.debug "Performing kexec call against #{node_url}"
|
178
|
+
resource = ::ForemanDiscovery::NodeAPI::Power.service(:url => node_url)
|
179
|
+
return true if resource.kexec(json)
|
180
|
+
rescue => e
|
181
|
+
msg = N_("Unable to perform kexec on %{name} (%{url}): %{msg}")
|
182
|
+
::Foreman::Logging.exception(msg % { :name => name, :url => node_url, :msg => e.to_s }, e)
|
183
|
+
if next_ip == self.ip
|
184
|
+
raise ::Foreman::WrappedException.new(e, msg, :name => name, :url => node_url, :msg => e.to_s)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
false
|
167
189
|
end
|
168
190
|
|
169
191
|
def self.model_name
|
@@ -27,7 +27,7 @@ module Host::ManagedExtensions
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def setReboot
|
30
|
-
old.becomes(Host::Discovered).reboot
|
30
|
+
old.becomes(Host::Discovered).reboot(facts["discovery_bootip"] || facts["ipaddress"])
|
31
31
|
# It is too late to report error in the post_queue, we catch them and
|
32
32
|
# continue. If flash is implemented for new hosts (http://projects.theforeman.org/issues/10559)
|
33
33
|
# we can report the error to the user perhaps.
|
@@ -10,39 +10,32 @@ class Setting::Discovered < ::Setting
|
|
10
10
|
BLANK_ATTRS << 'discovery_facts_ipmi'
|
11
11
|
BLANK_ATTRS << 'discovery_prefix'
|
12
12
|
|
13
|
-
def self.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
self.set('discovery_always_rebuild_dns', N_("Force DNS entries creation when provisioning discovered host"), true, N_("Force DNS")),
|
40
|
-
self.set('discovery_error_on_existing', N_("Do not allow to discover existing managed host matching MAC of a provisioning NIC (errors out early)"), false, N_("Error on existing NIC")),
|
41
|
-
self.set('discovery_naming', N_("Discovery hostname naming pattern"), 'Fact', N_("Type of name generator"), nil, {:collection => Proc.new {::Host::Discovered::NAMING_PATTERNS} }),
|
42
|
-
].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
|
43
|
-
end
|
44
|
-
|
45
|
-
true
|
13
|
+
def self.default_settings
|
14
|
+
[
|
15
|
+
self.set('discovery_location', N_("The default location to place discovered hosts in"), "", N_("Discovery location"), nil, { :collection => Proc.new {Hash[Location.all.map{|loc| [loc[:title], loc[:title]]}]} }),
|
16
|
+
self.set('discovery_organization', N_("The default organization to place discovered hosts in"), "", N_("Discovery organization"), nil, { :collection => Proc.new {Hash[Organization.all.map{|org| [org[:title], org[:title]]}]} }),
|
17
|
+
self.set('discovery_fact', N_("Fact name to use for primary interface detection"), "discovery_bootif", N_("Interface fact")),
|
18
|
+
self.set('discovery_auto_bond', N_("Automatic bond interface (if another interface is detected on the same VLAN via LLDP)"), false, N_("Create bond interfaces")),
|
19
|
+
self.set('discovery_clean_facts', N_("Clean all reported facts during provisioning (except discovery facts)"), false, N_("Clean all facts")),
|
20
|
+
self.set('discovery_hostname', N_("List of facts to use for the hostname (separated by comma, first wins)"), "discovery_bootif", N_("Hostname facts")),
|
21
|
+
self.set('discovery_auto', N_("Automatically provision newly discovered hosts, according to the provisioning rules"), false, N_("Auto provisioning")),
|
22
|
+
self.set('discovery_reboot', N_("Automatically reboot or kexec discovered host during provisioning"), true, N_("Reboot")),
|
23
|
+
self.set('discovery_prefix', N_("The default prefix to use for the host name, must start with a letter"), "mac", N_("Hostname prefix")),
|
24
|
+
self.set('discovery_fact_column', N_("Extra facter columns to show in host lists (separate by comma)"), "", N_("Fact columns")),
|
25
|
+
self.set('discovery_facts_highlights', N_("Regex to organize facts for highlights section - e.g. ^(abc|cde)$"), "", N_("Highlighted facts")),
|
26
|
+
self.set('discovery_facts_storage', N_("Regex to organize facts for storage section"), "", N_("Storage facts")),
|
27
|
+
self.set('discovery_facts_software', N_("Regex to organize facts for software section"), "", N_("Software facts")),
|
28
|
+
self.set('discovery_facts_hardware', N_("Regex to organize facts for hardware section"), "", N_("Hardware facts")),
|
29
|
+
self.set('discovery_facts_network', N_("Regex to organize facts for network section"), "", N_("Network facts")),
|
30
|
+
self.set('discovery_facts_ipmi', N_("Regex to organize facts for ipmi section"), "", N_("IPMI facts")),
|
31
|
+
self.set('discovery_lock', N_("Automatically generate PXE configuration to pin a newly discovered host to discovery"), false, N_("Lock PXE")),
|
32
|
+
self.set('discovery_pxelinux_lock_template', N_("PXELinux template to be used when pinning a host to discovery"), 'pxelinux_discovery', N_("Locked PXELinux template name"), nil, { :collection => Proc.new {Hash[ProvisioningTemplate.where(:template_kind => TemplateKind.find_by_name(:snippet)).map{|template| [template[:name], template[:name]]}]} }),
|
33
|
+
self.set('discovery_pxegrub_lock_template', N_("PXEGrub template to be used when pinning a host to discovery"), 'pxegrub_discovery', N_("Locked PXEGrub template name"), nil, { :collection => Proc.new {Hash[ProvisioningTemplate.where(:template_kind => TemplateKind.find_by_name(:snippet)).map{|template| [template[:name], template[:name]]}]} }),
|
34
|
+
self.set('discovery_pxegrub2_lock_template', N_("PXEGrub2 template to be used when pinning a host to discovery"), 'pxegrub2_discovery', N_("Locked PXEGrub2 template name"), nil, { :collection => Proc.new {Hash[ProvisioningTemplate.where(:template_kind => TemplateKind.find_by_name(:snippet)).map{|template| [template[:name], template[:name]]}]} }),
|
35
|
+
self.set('discovery_always_rebuild_dns', N_("Force DNS entries creation when provisioning discovered host"), true, N_("Force DNS")),
|
36
|
+
self.set('discovery_error_on_existing', N_("Do not allow to discover existing managed host matching MAC of a provisioning NIC (errors out early)"), false, N_("Error on existing NIC")),
|
37
|
+
self.set('discovery_naming', N_("Discovery hostname naming pattern"), 'Fact', N_("Type of name generator"), nil, {:collection => Proc.new {::Host::Discovered::NAMING_PATTERNS} }),
|
38
|
+
]
|
46
39
|
end
|
47
40
|
|
48
41
|
def self.discovery_fact_column_array
|
@@ -6,7 +6,7 @@ module ForemanDiscovery
|
|
6
6
|
raise(::Foreman::Exception.new(N_("Discovered host '%{host}' has all NICs filtered out, filter: %{filter}") %
|
7
7
|
{:host => host, :filter => Setting[:ignored_interface_identifiers]})) if interfaces.size == 0
|
8
8
|
bootif_mac = FacterUtils::bootif_mac(facts).try(:downcase)
|
9
|
-
detected = interfaces.detect { |_, values| values[:macaddress].try(:downcase) == bootif_mac && values[:ipaddress].present? }
|
9
|
+
detected = interfaces.detect { |_, values| values[:macaddress].try(:downcase) == bootif_mac && (values[:ipaddress].present? || values[:ipaddress6].present?) }
|
10
10
|
Rails.logger.debug "Discovery fact parser detected primary interface: #{detected}"
|
11
11
|
# return the detected interface as array [name, facts]
|
12
12
|
detected || raise(::Foreman::Exception.new(N_("Unable to find primary NIC with %{mac} specified via '%{fact}', NIC filter: %{filter}") %
|
@@ -1,7 +1,6 @@
|
|
1
1
|
class ForemanDiscovery::HostConverter
|
2
|
-
|
3
2
|
# Converts discovered host to managed host without uptading the database.
|
4
|
-
# Record must be saved explicitly (using save! or
|
3
|
+
# Record must be saved explicitly (using save! or update! or similar).
|
5
4
|
# Creates shallow copy.
|
6
5
|
def self.to_managed(original_host, set_managed = true, set_build = true, added_attributes = {})
|
7
6
|
host = original_host.becomes(::Host::Managed)
|
@@ -35,4 +34,33 @@ class ForemanDiscovery::HostConverter
|
|
35
34
|
host.build = true
|
36
35
|
end
|
37
36
|
|
37
|
+
def self.unused_ip_for_subnet(subnet, mac, existing_ip)
|
38
|
+
ipam = subnet.unused_ip(mac)
|
39
|
+
raise(::Foreman::Exception.new(N_("IPAM must be configured for subnet '%s'"), subnet)) unless ipam.present?
|
40
|
+
|
41
|
+
# None IPAM returns nil - in that case keep the current address
|
42
|
+
suggested_ip = ipam.suggest_ip
|
43
|
+
suggested_ip.nil? ? existing_ip : suggested_ip
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.unused_ip_for_host(host, new_subnet = nil, new_subnet6 = nil)
|
47
|
+
host.interfaces.each do |interface|
|
48
|
+
next unless interface.managed?
|
49
|
+
|
50
|
+
interface.subnet = new_subnet if new_subnet
|
51
|
+
interface.subnet6 = new_subnet6 if new_subnet6
|
52
|
+
interface.ip = unused_ip_for_subnet(interface.subnet, interface.mac, interface.ip) if interface.subnet
|
53
|
+
interface.ip6 = unused_ip_for_subnet(interface.subnet6, interface.mac, interface.ip6) if interface.subnet6
|
54
|
+
interface.save!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.change_subnet_and_unused_ip(host, hostgroup)
|
59
|
+
if host.subnet != hostgroup.subnet || host.subnet6 != hostgroup.subnet6
|
60
|
+
Rails.logger.debug "Discovered host subnets #{[host.subnet, host.subnet6]} do not match hostgroup subnets #{[hostgroup.subnet, hostgroup.subnet6]}"
|
61
|
+
unused_ip_for_host(host, host.hostgroup.subnet, host.hostgroup.subnet6)
|
62
|
+
else
|
63
|
+
Rails.logger.debug "Discovered host subnets #{[host.subnet, host.subnet6]} match hostgroup subnets"
|
64
|
+
end
|
65
|
+
end
|
38
66
|
end
|
@@ -4,14 +4,15 @@ module ForemanDiscovery
|
|
4
4
|
class SubnetAndTaxonomy < ImportHook
|
5
5
|
def after_populate
|
6
6
|
primary_ip = host.primary_interface.ip
|
7
|
+
primary_ip6 = host.primary_interface.ip6
|
7
8
|
|
8
|
-
unless primary_ip
|
9
|
+
unless primary_ip || primary_ip6
|
9
10
|
logger.warn "Unable to assign subnet - reboot trigger may not be possible, primary interface is missing IP address"
|
10
11
|
return
|
11
12
|
end
|
12
13
|
|
13
14
|
# set subnet
|
14
|
-
|
15
|
+
set_subnets(primary_ip, primary_ip6)
|
15
16
|
# set location and organization
|
16
17
|
set_location
|
17
18
|
set_organization
|
@@ -19,18 +20,9 @@ module ForemanDiscovery
|
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
-
host.primary_interface.subnet =
|
24
|
-
|
25
|
-
|
26
|
-
def suggested_subnet(ip)
|
27
|
-
subnet = Subnet.subnet_for(ip)
|
28
|
-
if subnet
|
29
|
-
logger.info "Detected subnet: #{subnet} with taxonomy #{subnet.organizations.collect(&:name)}/#{subnet.locations.collect(&:name)}"
|
30
|
-
else
|
31
|
-
logger.warn "Subnet could not be detected for #{ip}"
|
32
|
-
end
|
33
|
-
subnet
|
23
|
+
def set_subnets(ip, ip6)
|
24
|
+
host.primary_interface.subnet = ForemanDiscovery::SubnetSuggestion.for(ip: ip, kind: 'IPv4') if ip
|
25
|
+
host.primary_interface.subnet6 = ForemanDiscovery::SubnetSuggestion.for(ip: ip6, kind: 'IPv6') if ip6
|
34
26
|
end
|
35
27
|
|
36
28
|
def set_location
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ForemanDiscovery
|
2
|
+
class SubnetSuggestion
|
3
|
+
attr_accessor :ip, :kind
|
4
|
+
|
5
|
+
def self.for(ip:, kind:)
|
6
|
+
new(ip: ip, kind: kind).()
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(ip:, kind:)
|
10
|
+
self.ip = ip
|
11
|
+
self.kind = kind
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
return unless ip
|
16
|
+
|
17
|
+
subnet = Subnet.unscoped.subnet_for(ip)
|
18
|
+
if subnet
|
19
|
+
Rails.logger.info "Detected #{kind} subnet: #{subnet} with taxonomy #{subnet.organizations.collect(&:name)}/#{subnet.locations.collect(&:name)}"
|
20
|
+
else
|
21
|
+
Rails.logger.info "#{kind} subnet could not be detected for #{ip}"
|
22
|
+
end
|
23
|
+
subnet
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -4,25 +4,27 @@
|
|
4
4
|
<div class="modal-header">
|
5
5
|
<h4 class="modal-title" id="fixedPropertiesSelectorLabel">Select initial host properties</h4>
|
6
6
|
</div>
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
<%= form_for host, :url => edit_discovered_host_path(host), :method => :get do |f| %>
|
8
|
+
<div class="modal-body">
|
9
|
+
<%= select_f f, :hostgroup_id, accessible_resource_records(:hostgroup, :title).to_a, :id, :to_label,
|
10
|
+
{ :include_blank => true },
|
11
|
+
{ :help_inline => :indicator, :size => 'col-md-10' } %>
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
<% if show_organization_tab? %>
|
14
|
+
<%= select_f f, :organization_id, Organization.my_organizations, :id, :to_label, {}, {:size => 'col-md-10'} %>
|
15
|
+
<% end %>
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
<
|
24
|
-
|
25
|
-
|
17
|
+
<% if show_location_tab? %>
|
18
|
+
<%= select_f f, :location_id, Location.my_locations, :id, :to_label, {}, {:size => 'col-md-10'} %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<div>Changing the Host's Subnet is not possible via Customize Host form, use Create Host or Auto provisioning and set the desired Subnet in the Hostgroup.</div>
|
22
|
+
</div>
|
23
|
+
<div class="modal-footer">
|
24
|
+
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
25
|
+
<input type="submit" class="btn btn-default" value="<%= _('Customize Host') %>" />
|
26
|
+
<input type="submit" class="btn btn-primary" value="<%= _('Create Host') %>" name="quick_submit" />
|
27
|
+
</div>
|
26
28
|
<% end %>
|
27
29
|
</div>
|
28
30
|
</div>
|
@@ -28,7 +28,7 @@ Please read kexec(8) man page for more information about semantics.
|
|
28
28
|
options << @host.facts['append']
|
29
29
|
options << "domain=#{@host.domain}"
|
30
30
|
options << 'console-setup/ask_detect=false console-setup/layout=USA console-setup/variant=USA keyboard-configuration/layoutcode=us localechooser/translation/warn-light=true localechooser/translation/warn-severe=true'
|
31
|
-
options << "locale=#{
|
31
|
+
options << "locale=#{host_param('lang') || 'en_US'}"
|
32
32
|
options << "inst.stage2=#{@host.operatingsystem.medium_uri(@host)}" if @host.operatingsystem.name.match(/Atomic/i)
|
33
33
|
-%>
|
34
34
|
{
|
data/config/routes.rb
CHANGED
@@ -6,6 +6,8 @@ Rails.application.routes.draw do
|
|
6
6
|
post 'os_selected_discovered_hosts' => 'hosts#os_selected'
|
7
7
|
post 'medium_selected_discovered_hosts' => 'hosts#medium_selected'
|
8
8
|
|
9
|
+
get 'discovered_hosts/help', :action => :welcome, :controller => 'discovered_hosts'
|
10
|
+
|
9
11
|
constraints(:id => /[^\/]+/) do
|
10
12
|
resources :discovered_hosts, :except => [:new, :create] do
|
11
13
|
member do
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class RemoveOldDiscoveryReaderPermissions < ActiveRecord::Migration[4.2]
|
2
2
|
def up
|
3
3
|
Permission.where("name like '%_discovery_rules' and resource_type is null").each do |permission|
|
4
|
-
permission.
|
4
|
+
permission.update(:resource_type => 'DiscoveryRule')
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class RegenerateRedHatKexec < ActiveRecord::Migration[4.2]
|
2
2
|
def up
|
3
3
|
t = ProvisioningTemplate.find_by_name("Discovery Red Hat kexec")
|
4
|
-
t.
|
4
|
+
t.update(:template => t.template.sub(/rescue ''$/, 'if mac')) if t
|
5
5
|
end
|
6
6
|
|
7
7
|
def down
|
@@ -9,7 +9,7 @@
|
|
9
9
|
# and makes sure there are no two entities with the same priority.
|
10
10
|
DiscoveryRules.reset_column_information
|
11
11
|
DiscoveryRules.unscoped.reorder(:priority, :created_at).find_each do |rule|
|
12
|
-
rule.
|
12
|
+
rule.update!(:priority => score)
|
13
13
|
score += delta
|
14
14
|
end
|
15
15
|
change_column :discovery_rules, :priority, :integer, null: false
|
data/extra/discover-host
CHANGED
@@ -3,10 +3,12 @@ require 'optparse'
|
|
3
3
|
require 'json'
|
4
4
|
require 'rest-client'
|
5
5
|
|
6
|
-
def find_base name="default"
|
7
|
-
return name if File.
|
6
|
+
def find_base name = "default"
|
7
|
+
return name if File.exist?(name)
|
8
|
+
|
8
9
|
file = File.absolute_path(File.dirname(__FILE__) + "../../test/facts/#{name}.json")
|
9
|
-
raise "Unable to find file #{file}" unless File.
|
10
|
+
raise "Unable to find file #{file}" unless File.exist?(file)
|
11
|
+
|
10
12
|
file
|
11
13
|
end
|
12
14
|
|
@@ -14,6 +16,7 @@ base = find_base
|
|
14
16
|
version = "3.4.0"
|
15
17
|
interfaces = []
|
16
18
|
preserve_interfaces = false
|
19
|
+
use_facts_endpoint = false
|
17
20
|
primary = nil
|
18
21
|
bootif = nil
|
19
22
|
url = "http://admin:changeme@localhost:3000"
|
@@ -38,6 +41,10 @@ OptionParser.new do |opts|
|
|
38
41
|
preserve_interfaces = true
|
39
42
|
end
|
40
43
|
|
44
|
+
opts.on("-a", "--facts", "Use host facts endpoint") do |v|
|
45
|
+
use_facts_endpoint = true
|
46
|
+
end
|
47
|
+
|
41
48
|
opts.on("-pNAME", "--primary=NAME", "Interface to use as primary (defaults to the first one)") do |v|
|
42
49
|
primary = v
|
43
50
|
end
|
@@ -70,8 +77,8 @@ unless preserve_interfaces
|
|
70
77
|
json["interfaces"] = interfaces.map{|i| i.first}.join(',')
|
71
78
|
interfaces.each do |iface|
|
72
79
|
name, subnet, ipo, mac = iface
|
73
|
-
mac
|
74
|
-
ipo
|
80
|
+
mac ||= (["52"] + 5.times.map { '%02x' % rand(0..255) }).join(':')
|
81
|
+
ipo ||= rand(1..253)
|
75
82
|
ip = "192.168.#{subnet}.#{ipo}"
|
76
83
|
json["macaddress_#{name}"] = mac
|
77
84
|
json["ipaddress_#{name}"] = ip
|
@@ -83,7 +90,14 @@ unless preserve_interfaces
|
|
83
90
|
end
|
84
91
|
end
|
85
92
|
puts JSON.pretty_generate(json)
|
86
|
-
|
87
|
-
|
93
|
+
if use_facts_endpoint
|
94
|
+
endpoint = url + "/api/v2/hosts/facts"
|
95
|
+
payload = {"facts" => json, "name" => json["hostname"] || json["networking"]["fqdn"]}
|
96
|
+
else
|
97
|
+
endpoint = url + "/api/v2/discovered_hosts/facts"
|
98
|
+
payload = {"facts" => json}
|
99
|
+
end
|
100
|
+
resource = RestClient::Resource.new(endpoint, verify_ssl: OpenSSL::SSL::VERIFY_NONE)
|
101
|
+
response = resource.post(payload.to_json, {content_type: :json, accept: :json})
|
88
102
|
puts response.code
|
89
103
|
puts response.body
|