Class: ForemanDiscovery::HostConverter

Inherits:
Object
  • Object
show all
Defined in:
app/services/foreman_discovery/host_converter.rb

Class Method Summary collapse

Class Method Details

.change_subnet_and_unused_ip(host, hostgroup) ⇒ Object



73
74
75
76
77
78
79
80
# File 'app/services/foreman_discovery/host_converter.rb', line 73

def self.change_subnet_and_unused_ip(host, hostgroup)
  if host.subnet != hostgroup.subnet || host.subnet6 != hostgroup.subnet6
    Rails.logger.debug "Discovered host subnets #{[host.subnet, host.subnet6]} do not match hostgroup subnets #{[hostgroup.subnet, hostgroup.subnet6]}"
    unused_ip_for_host(host, host.hostgroup.subnet, host.hostgroup.subnet6)
  else
    Rails.logger.debug "Discovered host subnets #{[host.subnet, host.subnet6]} match hostgroup subnets"
  end
end

.ip_for_subnet(subnet, mac, ip) ⇒ Object



55
56
57
58
59
# File 'app/services/foreman_discovery/host_converter.rb', line 55

def self.ip_for_subnet(subnet, mac, ip) 
  return ip if ip && subnet&.unused_ip(mac)&.ip_include?(ip)

  unused_ip_for_subnet(subnet, mac, ip)
end

.set_build_clean_facts(host) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'app/services/foreman_discovery/host_converter.rb', line 21

def self.set_build_clean_facts(host)
  # fact cleaning
  if Setting['discovery_clean_facts']
    # clean all facts except those from Discovery
    host.define_singleton_method(:clear_facts) do
      keep_ids = FactValue.where(host_id: host.id, fact_names: { type: 'DiscoveryFactName' }).where("fact_names.name like 'discovery_%'").joins(:fact_name).pluck("fact_values.id")
      FactValue.where.not(id: keep_ids).delete_all
    end
  else
    # clean no facts (default behavior)
    host.define_singleton_method(:clear_facts) {}
  end
  # set build flag
  host.build = true
end

.to_managed(original_host, set_managed = true, set_build = true, added_attributes = {}) ⇒ Object

Converts discovered host to managed host without uptading the database. Record must be saved explicitly (using save! or update! or similar). Creates shallow copy.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'app/services/foreman_discovery/host_converter.rb', line 5

def self.to_managed(original_host, set_managed = true, set_build = true, added_attributes = {})
  host = original_host.becomes(::Host::Managed)
  host.type = 'Host::Managed'
  host.attributes = host.apply_inherited_attributes(added_attributes)
  host.set_hostgroup_defaults if host.hostgroup_id.present?

  # the following flags can be skipped when parameters are set to false
  if set_managed
    host.managed = set_managed
    host.primary_interface.managed = set_managed
  end
  # set build only and only on final save (facts are deleted)
  set_build_clean_facts(host) if set_build
  host
end

.unused_ip_for_host(host, new_subnet = nil, new_subnet6 = nil) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'app/services/foreman_discovery/host_converter.rb', line 61

def self.unused_ip_for_host(host, new_subnet = nil, new_subnet6 = nil)
  host.interfaces.each do |interface|
    next unless interface.managed?

    interface.subnet = new_subnet if new_subnet
    interface.subnet6 = new_subnet6 if new_subnet6

    interface.ip = ip_for_subnet(interface.subnet, interface.mac, interface.ip) if interface.subnet
    interface.ip6 = ip_for_subnet(interface.subnet6, interface.mac, interface.ip6) if interface.subnet6
  end
end

.unused_ip_for_subnet(subnet, mac, existing_ip) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/services/foreman_discovery/host_converter.rb', line 37

def self.unused_ip_for_subnet(subnet, mac, existing_ip)
  # prefer existing reservation to prevent conflicts
  existing_rec = subnet&.dhcp_proxy&.record(subnet.network, mac)

  if existing_rec && existing_rec.type == "reservation"
    # reuse the reservation
    existing_rec.ip
  else
    # no reservation - find new unused IP
    ipam = subnet.unused_ip(mac)
    raise(::Foreman::Exception.new(N_("IPAM must be configured for subnet '%s'"), subnet)) unless ipam.present?

    # None IPAM returns nil - in that case keep the current address
    suggested_ip = ipam.suggest_ip
    suggested_ip.nil? ? existing_ip : suggested_ip
  end
end