From 369ca45e4055329e33e784b4400cdfadf7735431 Mon Sep 17 00:00:00 2001
From: Ohad Levy <ohadlevy@gmail.com>
Date: Tue, 26 Oct 2010 16:56:24 +0200
Subject: [PATCH] Fixes #284 - Use MAC address if IP doesn't exist when tftp booting

* Uses any of the assoicated mac addresses (RH only) prior to IP
* Adds a new settings to not update mac or ip information to Foreman - used for cases
  where DHCP booting is done via a temporary dhcp range
---
 app/controllers/unattended_controller.rb |   27 ++++++++++++++-------------
 app/models/host.rb                       |   12 +++++++++---
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/app/controllers/unattended_controller.rb b/app/controllers/unattended_controller.rb
index e91b0a8..d9017c2 100644
--- a/app/controllers/unattended_controller.rb
+++ b/app/controllers/unattended_controller.rb
@@ -8,8 +8,7 @@ class UnattendedController < ApplicationController
     :jumpstart_profile, :jumpstart_finish, :pxe_kickstart_config, :pxe_debian_config]
 
   def kickstart
-    logger.info "#{controller_name}: Kickstart host #{@host.name}"
-    @dynamic = @host.diskLayout=~/^#Dynamic/
+    @dynamic   = @host.diskLayout =~ /^#Dynamic/
     @arch      = @host.architecture.name
     os         = @host.operatingsystem
     @osver     = os.major.to_i
@@ -37,7 +36,7 @@ class UnattendedController < ApplicationController
     unattended_local "preseed_finish"
   end
 
-# this actions is called by each operatingsystem post/finish script - it notify us that the OS installation is done.
+  # this actions is called by each operatingsystem post/finish script - it notify us that the OS installation is done.
   def built
     logger.info "#{controller_name}: #{@host.name} is Built!"
     @host.built
@@ -72,20 +71,21 @@ class UnattendedController < ApplicationController
       ip = request.env["HTTP_X_FORWARDED_FOR"] unless request.env["HTTP_X_FORWARDED_FOR"].nil?
     end
 
+    # search for a mac address in any of the RHN provsioning headers
+    # this section is kickstart only relevant
     maclist = []
-    maccond = "mac in ("
     unless request.env['HTTP_X_RHN_PROVISIONING_MAC_0'].nil?
-      request.env.keys.each { | header |
-        if header =~ /^HTTP_X_RHN_PROVISIONING_MAC_/ then
-          maccond << "?, "
-          maclist << request.env[header].split[1].downcase.strip
+      begin
+        request.env.keys.each do | header |
+          maclist << request.env[header].split[1].downcase.strip if header =~ /^HTTP_X_RHN_PROVISIONING_MAC_/
         end
-      }
+      rescue => e
+        logger.info "unknown RHN_PROVISIONING header #{e}"
+      end
     end
-    maccond.sub!(/, $/, ')')
 
-    conditions = (ip and (!maclist.empty?)) ? ["ip = ? and " + maccond, ip, *maclist] : ["ip = ?",ip];
-    logger.info "#{controller_name}: conditions string: " + conditions.to_s
+    # we try to match first based on the MAC, falling back to the IP
+    conditions = (!maclist.empty? ? {:mac => maclist} : {:ip => ip})
     @host = Host.find(:first, :include => [:architecture, :media, :operatingsystem, :domain], :conditions => conditions)
     if @host.nil?
       logger.info "#{controller_name}: unable to find ip/mac match for #{ip}"
@@ -96,10 +96,11 @@ class UnattendedController < ApplicationController
       logger.error "#{controller_name}: #{@host.name}'s operatingsytem [#{@host.operatingsystem.fullname}] has no OS family!"
       head(:conflict) and return
     end
+    logger.info "Found #{@host}"
   end
 
   def allowed_to_install?
-    @host.build or @spoof ? true : head(:method_not_allowed)
+    (@host.build or @spoof) ? true : head(:method_not_allowed)
   end
 
   # Cleans Certificate and enable autosign
diff --git a/app/models/host.rb b/app/models/host.rb
index ac05700..55f9fd6 100644
--- a/app/models/host.rb
+++ b/app/models/host.rb
@@ -208,6 +208,10 @@ class Host < Puppet::Rails::Host
     # maybe these should be moved to the common parameters, leaving them in for now
     param["puppetmaster"] = puppetmaster
     param["domainname"] = domain.fullname unless domain.nil? or domain.fullname.nil?
+    if SETTINGS[:ignore_puppet_facts_for_provisioning]
+      param["ip"]  = ip
+      param["mac"] = mac
+    end
     param.update self.params
 
     info_hash = {}
@@ -279,15 +283,17 @@ class Host < Puppet::Rails::Host
   end
 
   def populateFieldsFromFacts
-    self.mac = fv(:macaddress)
-    self.ip = fv(:ipaddress) if ip.nil?
+    unless SETTINGS[:ignore_puppet_facts_for_provisioning]
+      self.mac = fv(:macaddress)
+      self.ip = fv(:ipaddress) if ip.nil?
+    end
     self.domain = Domain.find_or_create_by_name fv(:domain) unless fv(:domain).empty?
     # On solaris architecture fact is harwareisa
     if myarch=fv(:architecture) || fv(:hardwareisa)
       self.arch=Architecture.find_or_create_by_name myarch unless myarch.empty?
     end
     # by default, puppet doesnt store an env name in the database
-    env=fv(:environment) || "production"
+    env=fv(:environment) || SETTINGS[:default_puppet_environment] || "production"
     self.environment ||= Environment.find_or_create_by_name env
 
     os_name = fv(:operatingsystem)
-- 
1.7.2.3

