foreman/app/controllers/unattended_controller.rb @ 71b45148
18738311 | Ohad Levy | class UnattendedController < ApplicationController
|
|
b4b14336 | Ohad Levy | layout nil
|
|
69fd03eb | Ohad Levy | ||
a6db0470 | Paul Kelly | # Methods which return configuration files for syslinux(pxe), pxegrub or g/ipxe
|
|
017e1049 | Ohad Levy | PXE_CONFIG_URLS = [:pxe_kickstart_config, :pxe_debian_config, :pxemenu] + TemplateKind.where("name LIKE ?","pxelinux").map(&:name)
|
|
PXEGRUB_CONFIG_URLS = [:pxe_jumpstart_config] + TemplateKind.where("name LIKE ?", "pxegrub").map(&:name)
|
|||
GPXE_CONFIG_URLS = [:gpxe_kickstart_config] + TemplateKind.where("name LIKE ?", "gpxe").map(&:name)
|
|||
a6db0470 | Paul Kelly | CONFIG_URLS = PXE_CONFIG_URLS + GPXE_CONFIG_URLS + PXEGRUB_CONFIG_URLS
|
|
69fd03eb | Ohad Levy | # Methods which return valid provision instructions, used by the OS
|
|
017e1049 | Ohad Levy | PROVISION_URLS = [:kickstart, :preseed, :jumpstart ] + TemplateKind.where("name LIKE ?", "provision").map(&:name)
|
|
69fd03eb | Ohad Levy | # Methods which returns post install instructions for OS's which require it
|
|
017e1049 | Ohad Levy | FINISH_URLS = [:preseed_finish, :jumpstart_finish] + TemplateKind.where("name LIKE ?", "finish").map(&:name)
|
|
69fd03eb | Ohad Levy | ||
# We dont require any of these methods for provisioning
|
|||
d7bd2f22 | Ohad Levy | skip_before_filter :require_ssl, :require_login, :authorize, :session_expiry, :update_activity_time
|
|
69fd03eb | Ohad Levy | ||
224783a1 | Ohad Levy | # require logged in user to see templates in spoof mode
|
|
before_filter do |c|
|
|||
c.send(:require_login) if c.params.keys.include?("spoof")
|
|||
end
|
|||
69fd03eb | Ohad Levy | # We want to find out our requesting host
|
|
77440fe6 | Ohad Levy | before_filter :get_host_details, :allowed_to_install?, :except => :template
|
|
69fd03eb | Ohad Levy | before_filter :handle_ca, :only => PROVISION_URLS
|
|
cab0d8c6 | Ohad Levy | # load "helper" variables to be available in the templates
|
|
before_filter :load_template_vars, :only => PROVISION_URLS
|
|||
77440fe6 | Ohad Levy | before_filter :pxe_config, :only => CONFIG_URLS
|
|
69fd03eb | Ohad Levy | # all of our requests should be returned in text/plain
|
|
after_filter :set_content_type
|
|||
23e59327 | Ohad Levy | before_filter :set_admin_user, :only => :built
|
|
18738311 | Ohad Levy | ||
def kickstart
|
|||
69fd03eb | Ohad Levy | unattended_local
|
|
18738311 | Ohad Levy | end
|
|
def preseed
|
|||
69fd03eb | Ohad Levy | unattended_local
|
|
18738311 | Ohad Levy | end
|
|
26a8190e | Ohad Levy | def preseed_finish
|
|
69fd03eb | Ohad Levy | unattended_local
|
|
26a8190e | Ohad Levy | end
|
|
d97375e0 | Ohad Levy | # this actions is called by each operatingsystem post/finish script - it notify us that the OS installation is done.
|
|
b4b14336 | Ohad Levy | def built
|
|
22924f15 | Ohad Levy | logger.info "#{controller_name}: #{@host.name} is Built!"
|
|
b34e9aea | Ohad Levy | head(@host.built ? :created : :conflict)
|
|
b4b14336 | Ohad Levy | end
|
|
e5d3f34e | Ohad Levy | def template
|
|
return head(:not_found) unless (params.has_key?("id") and params.has_key?(:hostgroup))
|
|||
template = ConfigTemplate.find_by_name(params['id'])
|
|||
@host = Hostgroup.find_by_name(params['hostgroup'])
|
|||
return head(:not_found) unless template and @host
|
|||
load_template_vars if template.template_kind.name == 'provision'
|
|||
67799065 | Ohad Levy | safe_render template.template
|
|
e5d3f34e | Ohad Levy | end
|
|
14dd0353 | Ohad Levy | # Returns a valid GPXE config file to kickstart hosts
|
|
def gpxe_kickstart_config
|
|||
end
|
|||
218bd6e0 | Justin Sherrill | def pxe_config
|
|
@kernel = @host.operatingsystem.kernel @host.arch
|
|||
@initrd = @host.operatingsystem.initrd @host.arch
|
|||
6352d882 | Jochen Schalanda | end
|
|
cab0d8c6 | Ohad Levy | # Generate an action for each template kind
|
|
# i.e. /unattended/provision will render the provisioning template for the requesting host
|
|||
TemplateKind.all.each do |kind|
|
|||
define_method kind.name do
|
|||
@type = kind.name
|
|||
unattended_local
|
|||
end
|
|||
end
|
|||
18738311 | Ohad Levy | private
|
|
224783a1 | Ohad Levy | ||
1b23d712 | Ohad Levy | # lookup for a host based on the ip address and if possible by a mac address(as sent by anaconda)
|
|
# if the host was found than its record will be in @host
|
|||
# if the host doesn't exists, it will return 404 and the requested method will not be reached.
|
|||
18738311 | Ohad Levy | def get_host_details
|
|
# find out ip info
|
|||
if params.has_key? "spoof"
|
|||
ip = params.delete("spoof")
|
|||
a79cf03f | Ohad Levy | @spoof = true
|
|
18738311 | Ohad Levy | elsif (ip = request.env['REMOTE_ADDR']) =~ /127.0.0/
|
|
ip = request.env["HTTP_X_FORWARDED_FOR"] unless request.env["HTTP_X_FORWARDED_FOR"].nil?
|
|||
end
|
|||
267f1ea2 | Ohad Levy | ip = ip.split(',').first # in cases where multiple nics/ips exists - see #1619
|
|
4ebe38c7 | Ohad Levy | # search for a mac address in any of the RHN provisioning headers
|
|
d97375e0 | Ohad Levy | # this section is kickstart only relevant
|
|
924cdd0a | Frank Sweetser | maclist = []
|
|
18738311 | Ohad Levy | unless request.env['HTTP_X_RHN_PROVISIONING_MAC_0'].nil?
|
|
d97375e0 | Ohad Levy | begin
|
|
request.env.keys.each do | header |
|
|||
maclist << request.env[header].split[1].downcase.strip if header =~ /^HTTP_X_RHN_PROVISIONING_MAC_/
|
|||
924cdd0a | Frank Sweetser | end
|
|
d97375e0 | Ohad Levy | rescue => e
|
|
logger.info "unknown RHN_PROVISIONING header #{e}"
|
|||
end
|
|||
18738311 | Ohad Levy | end
|
|
d97375e0 | Ohad Levy | # we try to match first based on the MAC, falling back to the IP
|
|
71b45148 | Ohad Levy | conditions = maclist.empty? ? {:ip => ip} : [ "lower(mac) IN (?)", maclist.map(&:downcase) ]
|
|
4ebe38c7 | Ohad Levy | @host = Host.first(:include => [:architecture, :medium, :operatingsystem, :domain], :conditions => conditions)
|
|
b34e9aea | Ohad Levy | unless @host
|
|
924cdd0a | Frank Sweetser | logger.info "#{controller_name}: unable to find ip/mac match for #{ip}"
|
|
286a2207 | Ohad Levy | head(:not_found) and return
|
|
18738311 | Ohad Levy | end
|
|
b34e9aea | Ohad Levy | unless @host.operatingsystem
|
|
4ebe38c7 | Ohad Levy | logger.error "#{controller_name}: #{@host.name}'s operating system is missing!"
|
|
b34e9aea | Ohad Levy | head(:conflict) and return
|
|
end
|
|||
unless @host.operatingsystem.family
|
|||
2c83f744 | Paul Kelly | # Then, for some reason, the OS has not been specialized into a Redhat or Debian class
|
|
4ebe38c7 | Ohad Levy | logger.error "#{controller_name}: #{@host.name}'s operating system [#{@host.operatingsystem.fullname}] has no OS family!"
|
|
2c83f744 | Paul Kelly | head(:conflict) and return
|
|
end
|
|||
d97375e0 | Ohad Levy | logger.info "Found #{@host}"
|
|
18738311 | Ohad Levy | end
|
|
a79cf03f | Ohad Levy | def allowed_to_install?
|
|
d97375e0 | Ohad Levy | (@host.build or @spoof) ? true : head(:method_not_allowed)
|
|
a79cf03f | Ohad Levy | end
|
|
36f93e4d | Ohad Levy | # Cleans Certificate and enable autosign. This is run as a before_filter for provisioning templates.
|
|
# The host is requesting its build configuration so I guess we just send them some text so a post mortum can see what happened
|
|||
a79cf03f | Ohad Levy | def handle_ca
|
|
36f93e4d | Ohad Levy | # The reason we do it here is to minimize the amount of time it is possible to automatically get a certificate
|
|
07723734 | Ohad Levy | ||
36f93e4d | Ohad Levy | # We don't do anything if we are in spoof mode.
|
|
return true if @spoof
|
|||
07723734 | Ohad Levy | ||
26f75f44 | Ewoud Kohl van Wijngaarden | # This should terminate the before_filter and the action. We return a HTTP
|
|
# error so the installer knows something is wrong. This is tested with
|
|||
# Anaconda, but maybe Suninstall will choke on it.
|
|||
render(:text => "Failed to clean any old certificates or add the autosign entry. Terminating the build!", :status => 500) unless @host.handle_ca
|
|||
36f93e4d | Ohad Levy | #TODO: Email the user who initiated this build operation.
|
|
a79cf03f | Ohad Levy | end
|
|
0c759d7b | Ohad Levy | ||
cab0d8c6 | Ohad Levy | # we try to find this host specific template
|
|
4ebe38c7 | Ohad Levy | # if it doesn't exists, we'll try to find a local generic template
|
|
cab0d8c6 | Ohad Levy | # otherwise render the default view
|
|
69fd03eb | Ohad Levy | def unattended_local
|
|
67799065 | Ohad Levy | if (config = @host.configTemplate({ :kind => @type }))
|
|
cab0d8c6 | Ohad Levy | logger.debug "rendering DB template #{config.name} - #{@type}"
|
|
218bd6e0 | Justin Sherrill | safe_render config and return
|
|
cab0d8c6 | Ohad Levy | end
|
|
type = "unattended_local/#{request.path.gsub("/#{controller_name}/","")}.local"
|
|||
017e1049 | Ohad Levy | render :template => type if File.exists?("#{Rails.root}/app/views/#{type}.rhtml")
|
|
0c759d7b | Ohad Levy | end
|
|
d8dd4f92 | Jon Fautley | def set_content_type
|
|
b34e9aea | Ohad Levy | response.headers['Content-Type'] = 'text/plain'
|
|
d8dd4f92 | Jon Fautley | end
|
|
cab0d8c6 | Ohad Levy | def load_template_vars
|
|
# load the os family default variables
|
|||
eval "#{@host.os.pxe_type}_attributes"
|
|||
end
|
|||
a6db0470 | Paul Kelly | def jumpstart_attributes
|
|
if @host.operatingsystem.supports_image and @host.use_image
|
|||
@install_type = "flash_install"
|
|||
# We have an individual override for the host's image file
|
|||
if @host.image_file
|
|||
@archive_location = @host.image_file
|
|||
else
|
|||
@archive_location = @host.default_image_file
|
|||
end
|
|||
else
|
|||
@install_type = "initial_install"
|
|||
@system_type = "standalone"
|
|||
@cluster = "SUNWCreq"
|
|||
@locale = "C"
|
|||
end
|
|||
@disk = @host.diskLayout
|
|||
end
|
|||
cab0d8c6 | Ohad Levy | def kickstart_attributes
|
|
@dynamic = @host.diskLayout =~ /^#Dynamic/
|
|||
@arch = @host.architecture.name
|
|||
os = @host.operatingsystem
|
|||
@osver = os.major.to_i
|
|||
db59a916 | Jochen Schalanda | @mediapath = os.mediumpath @host
|
|
cab0d8c6 | Ohad Levy | @epel = os.epel @host
|
|
@yumrepo = os.yumrepo @host
|
|||
68f7a705 | Ohad Levy | # force static network configuration if static http parameter is defined, in the future this needs to go into the GUI
|
|
cab0d8c6 | Ohad Levy | @static = !params[:static].empty?
|
|
end
|
|||
def preseed_attributes
|
|||
@preseed_path = @host.os.preseed_path @host
|
|||
@preseed_server = @host.os.preseed_server @host
|
|||
end
|
|||
68f7a705 | Ohad Levy | def yast_attributes
|
|
end
|
|||
33031581 | Greg Sutcliffe | def aif_attributes
|
|
os = @host.operatingsystem
|
|||
@mediapath = os.mediumpath @host
|
|||
end
|
|||
e5d3f34e | Ohad Levy | private
|
|
def safe_render template
|
|||
218bd6e0 | Justin Sherrill | template_name = ""
|
|
if template.is_a?(String)
|
|||
@unsafe_template = template
|
|||
elsif template.is_a?(ConfigTemplate)
|
|||
@unsafe_template = template.template
|
|||
template_name = template.name
|
|||
else
|
|||
raise "unknown template"
|
|||
end
|
|||
begin
|
|||
b5029ab9 | Ohad Levy | render :inline => "<%= unattended_render(@unsafe_template).html_safe %>" and return
|
|
218bd6e0 | Justin Sherrill | rescue Exception => exc
|
|
msg = "There was an error rendering the " + template_name + " template: "
|
|||
render :text => msg + exc.message, :status => 500 and return
|
|||
end
|
|||
e5d3f34e | Ohad Levy | end
|
|
18738311 | Ohad Levy | end
|