foreman/app/models/orchestration/dhcp.rb @ 017a7d84
90b83222 | Ohad Levy | module Orchestration::DHCP
|
|
def self.included(base)
|
|||
base.send :include, InstanceMethods
|
|||
base.class_eval do
|
|||
ac36e7ce | Ohad Levy | after_validation :queue_dhcp
|
|
a6f4f5f7 | Ohad Levy | before_destroy :queue_dhcp_destroy
|
|
validate :ip_belongs_to_subnet?, :valid_jumpstart_model
|
|||
90b83222 | Ohad Levy | end
|
|
end
|
|||
module InstanceMethods
|
|||
def dhcp?
|
|||
dd42df0a | Ohad Levy | !subnet.nil? and subnet.dhcp? and managed? and capabilities.include?(:build)
|
|
90b83222 | Ohad Levy | end
|
|
a6f4f5f7 | Ohad Levy | def sp_dhcp?
|
|
30ae12bf | Ohad Levy | sp_valid? and !sp_subnet.nil? and sp_subnet.dhcp?
|
|
a6f4f5f7 | Ohad Levy | end
|
|
90b83222 | Ohad Levy | ||
a6f4f5f7 | Ohad Levy | def dhcp_record
|
|
639518c8 | Ohad Levy | return unless dhcp? or @dhcp_record
|
|
0c3e15d2 | Ohad Levy | @dhcp_record ||= jumpstart? ? Net::DHCP::SparcRecord.new(dhcp_attrs) : Net::DHCP::Record.new(dhcp_attrs)
|
|
90b83222 | Ohad Levy | end
|
|
a6f4f5f7 | Ohad Levy | def sp_dhcp_record
|
|
639518c8 | Ohad Levy | return unless sp_dhcp? or @sp_dhcp_record
|
|
0c3e15d2 | Ohad Levy | @sp_dhcp_record ||= Net::DHCP::Record.new sp_dhcp_attrs
|
|
90b83222 | Ohad Levy | end
|
|
a6f4f5f7 | Ohad Levy | protected
|
|
def set_dhcp
|
|||
dhcp_record.create
|
|||
90b83222 | Ohad Levy | end
|
|
30ae12bf | Ohad Levy | def set_dhcp_conflicts
|
|
dhcp_record.conflicts.each{|conflict| conflict.create}
|
|||
end
|
|||
a6f4f5f7 | Ohad Levy | def set_sp_dhcp
|
|
sp_dhcp_record.create
|
|||
end
|
|||
672f931d | Paul Kelly | ||
30ae12bf | Ohad Levy | def set_sp_dhcp_conflicts
|
|
sp_dhcp_record.conflicts.each{|conflict| conflict.create}
|
|||
end
|
|||
a6f4f5f7 | Ohad Levy | def del_dhcp
|
|
dhcp_record.destroy
|
|||
end
|
|||
672f931d | Paul Kelly | ||
30ae12bf | Ohad Levy | def del_dhcp_conflicts
|
|
dhcp_record.conflicts.each{|conflict| conflict.destroy}
|
|||
end
|
|||
a6f4f5f7 | Ohad Levy | def del_sp_dhcp
|
|
sp_dhcp_record.destroy
|
|||
end
|
|||
30ae12bf | Ohad Levy | def del_sp_dhcp_conflicts
|
|
sp_dhcp_record.conflicts.each{|conflict| conflict.destroy}
|
|||
end
|
|||
a6f4f5f7 | Ohad Levy | private
|
|
# returns a hash of dhcp record settings
|
|||
def dhcp_attrs
|
|||
return unless dhcp?
|
|||
dhcp_attr = { :name => name, :filename => operatingsystem.boot_filename(self),
|
|||
:ip => ip, :mac => mac, :hostname => name, :proxy => proxy_for_host,
|
|||
:network => subnet.network, :nextServer => boot_server }
|
|||
792573df | Paul Kelly | ||
a6f4f5f7 | Ohad Levy | if jumpstart?
|
|
jumpstart_arguments = os.jumpstart_params self, model.vendor_class
|
|||
672f931d | Paul Kelly | dhcp_attr.merge! jumpstart_arguments unless jumpstart_arguments.empty?
|
|
end
|
|||
a6f4f5f7 | Ohad Levy | dhcp_attr
|
|
90b83222 | Ohad Levy | end
|
|
a6f4f5f7 | Ohad Levy | # returns a hash of service processor / ilo dhcp record settings
|
|
def sp_dhcp_attrs
|
|||
return unless sp_dhcp?
|
|||
cc7fae9c | Ohad Levy | { :hostname => sp_name, :name => sp_name, :ip => sp_ip, :mac => sp_mac, :proxy => proxy_for_sp, :network => sp_subnet.network }
|
|
90b83222 | Ohad Levy | end
|
|
b79bd65c | Ohad Levy | # where are we booting from
|
|
90b83222 | Ohad Levy | def boot_server
|
|
b79bd65c | Ohad Levy | # if we don't manage tftp at all, we dont create a next-server entry.
|
|
6285a614 | Ohad Levy | return unless tftp?
|
|
b79bd65c | Ohad Levy | ||
a7ad2c1c | Ohad Levy | # first try to ask our TFTP server for its boot server
|
|
a6f4f5f7 | Ohad Levy | bs = tftp.bootServer
|
|
a7ad2c1c | Ohad Levy | # if that failed, trying to guess out tftp next server based on the smart proxy hostname
|
|
30ae12bf | Ohad Levy | bs ||= URI.parse(subnet.tftp.url).host
|
|
a7ad2c1c | Ohad Levy | # now convert it into an ip address (see http://theforeman.org/issues/show/1381)
|
|
return to_ip_address(bs) if bs.present?
|
|||
17ae1ec8 | Ohad Levy | failure "Unable to determine the host's boot server. The DHCP smart proxy failed to provide this information and this subnet is not provided with TFTP services."
|
|
rescue => e
|
|||
failure "failed to detect boot server: #{e}"
|
|||
90b83222 | Ohad Levy | end
|
|
def queue_dhcp
|
|||
30ae12bf | Ohad Levy | return unless (dhcp? or (old and old.dhcp?) or sp_dhcp? or (old and old.sp_dhcp?)) and orchestration_errors?
|
|
queue_remove_dhcp_conflicts if dhcp_conflict_detected?
|
|||
90b83222 | Ohad Levy | new_record? ? queue_dhcp_create : queue_dhcp_update
|
|
end
|
|||
def queue_dhcp_create
|
|||
30ae12bf | Ohad Levy | logger.debug "Scheduling new DHCP reservations"
|
|
queue.create(:name => "Create DHCP Settings for #{self}", :priority => 10,
|
|||
f28a6895 | Ohad Levy | :action => [self, :set_dhcp]) if dhcp?
|
|
30ae12bf | Ohad Levy | queue.create(:name => "Create DHCP Settings for #{sp_name}", :priority => 15,
|
|
a6f4f5f7 | Ohad Levy | :action => [self, :set_sp_dhcp]) if sp_dhcp?
|
|
90b83222 | Ohad Levy | end
|
|
def queue_dhcp_update
|
|||
f28a6895 | Ohad Levy | if dhcp_update_required?
|
|
bf988b94 | Ohad Levy | logger.debug("Detected a changed required for DHCP record")
|
|
30ae12bf | Ohad Levy | queue.create(:name => "Remove DHCP Settings for #{old}", :priority => 5,
|
|
f28a6895 | Ohad Levy | :action => [old, :del_dhcp]) if old.dhcp?
|
|
017a7d84 | Ohad Levy | queue.create(:name => "Create DHCP Settings for #{self}", :priority => 9,
|
|
f28a6895 | Ohad Levy | :action => [self, :set_dhcp]) if dhcp?
|
|
end
|
|||
if sp_dhcp_update_required?
|
|||
bf988b94 | Ohad Levy | logger.debug("Detected a changed required for BMC DHCP record")
|
|
30ae12bf | Ohad Levy | queue.create(:name => "Remove DHCP Settings for #{old.sp_name}", :priority => 5,
|
|
f28a6895 | Ohad Levy | :action => [old, :del_sp_dhcp]) if old.sp_dhcp?
|
|
017a7d84 | Ohad Levy | queue.create(:name => "Create DHCP Settings for #{sp_name}", :priority => 14,
|
|
f28a6895 | Ohad Levy | :action => [self, :set_sp_dhcp]) if sp_dhcp?
|
|
end
|
|||
a6f4f5f7 | Ohad Levy | end
|
|
# do we need to update our dhcp reservations
|
|||
def dhcp_update_required?
|
|||
# IP Address / name changed
|
|||
f28a6895 | Ohad Levy | return true if ((old.ip != ip) or (old.name != name) or (old.mac != mac) or (old.subnet != subnet))
|
|
672f931d | Paul Kelly | # Handle jumpstart
|
|
if jumpstart?
|
|||
if !old.build? or (old.medium != medium or old.arch != arch) or
|
|||
a6f4f5f7 | Ohad Levy | (os and old.os and (old.os.name != os.name or old.os != os))
|
|
return true
|
|||
672f931d | Paul Kelly | end
|
|
end
|
|||
a6f4f5f7 | Ohad Levy | false
|
|
end
|
|||
def sp_dhcp_update_required?
|
|||
f28a6895 | Ohad Levy | return true if ((old.sp_name != sp_name) or (old.sp_mac != sp_mac) or (old.sp_ip != sp_ip) or (old.sp_subnet != sp_subnet))
|
|
a6f4f5f7 | Ohad Levy | false
|
|
90b83222 | Ohad Levy | end
|
|
672f931d | Paul Kelly | def queue_dhcp_destroy
|
|
90b83222 | Ohad Levy | return unless dhcp? and errors.empty?
|
|
30ae12bf | Ohad Levy | queue.create(:name => "Remove DHCP Settings for #{self}", :priority => 5,
|
|
a6f4f5f7 | Ohad Levy | :action => [self, :del_dhcp])
|
|
30ae12bf | Ohad Levy | queue.create(:name => "Remove DHCP Settings for #{sp_name}", :priority => 5,
|
|
a6f4f5f7 | Ohad Levy | :action => [self, :del_sp_dhcp]) if sp_valid?
|
|
90b83222 | Ohad Levy | true
|
|
end
|
|||
30ae12bf | Ohad Levy | def queue_remove_dhcp_conflicts
|
|
return unless dhcp? and errors.any? and errors.are_all_conflicts?
|
|||
return unless overwrite?
|
|||
logger.debug "Scheduling DHCP conflicts removal"
|
|||
queue.create(:name => "DHCP conflicts removal for #{self}", :priority => 5,
|
|||
:action => [self, :del_dhcp_conflicts]) if dhcp_record and dhcp_record.conflicting?
|
|||
queue.create(:name => "DHCP conflicts removal for #{sp_name}", :priority => 5,
|
|||
:action => [self, :del_sp_dhcp_conflicts]) if sp_valid? and sp_dhcp and sp_dhcp_record.conflicting?
|
|||
end
|
|||
90b83222 | Ohad Levy | def ip_belongs_to_subnet?
|
|
return if subnet.nil? or ip.nil?
|
|||
return unless dhcp?
|
|||
unless subnet.contains? ip
|
|||
errors.add :ip, "Does not match selected Subnet"
|
|||
return false
|
|||
end
|
|||
a6f4f5f7 | Ohad Levy | rescue
|
|
90b83222 | Ohad Levy | # probably an invalid ip / subnet were entered
|
|
# we let other validations handle that
|
|||
end
|
|||
a6f4f5f7 | Ohad Levy | ||
def valid_jumpstart_model
|
|||
return unless jumpstart?
|
|||
dfa12d91 | Ohad Levy | errors.add :model_id, "is required for Solaris SPARC deployment" if model.blank?
|
|
errors.add :model_id, "Has an unknown vendor class" if model and model.vendor_class.empty?
|
|||
a6f4f5f7 | Ohad Levy | false
|
|
end
|
|||
def proxy_for_host
|
|||
6285a614 | Ohad Levy | subnet.dhcp_proxy
|
|
a6f4f5f7 | Ohad Levy | end
|
|
def proxy_for_sp
|
|||
6285a614 | Ohad Levy | sp_subnet.dhcp_proxy
|
|
a6f4f5f7 | Ohad Levy | end
|
|
30ae12bf | Ohad Levy | ||
def dhcp_conflict_detected?
|
|||
# we can't do any dhcp based validations when our MAC address is defined afterwards (e.g. in vm creation)
|
|||
return false if mac.blank? or name.blank?
|
|||
# This is an expensive operation and we will only do it if the DNS validation failed. This will ensure
|
|||
# that we report on both DNS and DHCP conflicts when we offer to remove collisions. It retrieves and
|
|||
# caches the conflicting records so we must always do it when overwriting
|
|||
return false unless (errors.any? and errors.are_all_conflicts?) or overwrite?
|
|||
return false unless dhcp?
|
|||
status = true
|
|||
status = failure("DHCP record #{dhcp_record.conflicts[0]} already exists", nil, :conflict) if dhcp_record and dhcp_record.conflicting?
|
|||
status &= failure("DHCP record #{sp_dhcp_record.conflicts[0]} already exists", nil, :conflict) if sp_dhcp? and sp_dhcp_record and sp_dhcp_record.conflicting?
|
|||
overwrite? ? errors.are_all_conflicts? : status
|
|||
end
|
|||
90b83222 | Ohad Levy | end
|
|
end
|