Project

General

Profile

Download (8.37 KB) Statistics
| Branch: | Tag: | Revision:
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