Skip to content

Commit

Permalink
Fixes #4413 - UEFI support for full and generic
Browse files Browse the repository at this point in the history
  • Loading branch information
lzap committed Jun 15, 2020
1 parent d018c26 commit 09dc92d
Show file tree
Hide file tree
Showing 21 changed files with 450 additions and 172 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ TFTP settings are needed.
<th>DHCP reservation</th>
<th>Pre-register host</th>
<th>OS-specific</th>
<th>EFI supported</th>
</tr>
<tr>
<td>Per-host image</td>
Expand All @@ -127,6 +128,7 @@ TFTP settings are needed.
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Full host image</td>
Expand All @@ -135,6 +137,7 @@ TFTP settings are needed.
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Generic image</td>
Expand All @@ -143,6 +146,7 @@ TFTP settings are needed.
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Subnet image</td>
Expand All @@ -151,6 +155,7 @@ TFTP settings are needed.
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
</table>

Expand Down
12 changes: 5 additions & 7 deletions app/controllers/foreman_bootdisk/api/v2/disks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ def index; end

api :GET, '/generic', N_('Download generic image')
def generic
# EFI not supported for iPXE generic bootdisk
tmpl = ForemanBootdisk::Renderer.new.generic_template_render
ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl) do |iso|
send_data read_file(iso), filename: "bootdisk_#{URI.parse(Setting[:foreman_url]).host}.iso"
send_file(iso, filename: "bootdisk_#{URI.parse(Setting[:foreman_url]).host}.iso")
end
end

Expand All @@ -34,22 +35,19 @@ def host
host = @disk
if params[:full]
ForemanBootdisk::ISOGenerator.generate_full_host(host) do |iso|
send_data read_file(iso), filename: "#{host.name}#{ForemanBootdisk::ISOGenerator.token_expiry(host)}.iso"
send_file(iso, filename: "#{host.name}#{ForemanBootdisk::ISOGenerator.token_expiry(host)}.iso")
end
else
# EFI not supported for iPXE host bootdisk
tmpl = host.bootdisk_template_render
ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl) do |iso|
send_data read_file(iso), filename: "#{host.name}.iso"
send_file(iso, filename: "#{host.name}.iso")
end
end
end

private

def read_file(filename)
File.read(filename)
end

def resource_scope
Host::Managed.authorized('view_hosts')
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ def index; end
def subnet
subnet = @subnet_disk
subnet.tftp || raise(::Foreman::Exception.new(N_('TFTP feature not enabled for subnet %s'), subnet.name))
tmpl = ForemanBootdisk::Renderer.new.generic_template_render(subnet)
ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl) do |iso|
name = subnet.name
send_data File.read(iso), filename: "bootdisk_subnet_#{name}.iso"
tmpl_bios = ForemanBootdisk::Renderer.new.generic_template_render(subnet)
tmpl_efi = nil
if subnet.httpboot
tmpl_efi = ForemanBootdisk::Renderer.new.generic_efi_template_render(subnet)
else
ForemanBootdisk.logger.warn('HTTPBOOT feature is not enabled for subnet %s, UEFI may not be available for bootdisk' % subnet.name)
end
ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl_bios, grub: tmpl_efi) do |temp_iso_filename|
send_file(temp_iso_filename, filename: subnet.name)
end
end

Expand Down
21 changes: 11 additions & 10 deletions app/controllers/foreman_bootdisk/disks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class DisksController < ::ApplicationController

def generic
begin
# EFI not supported for iPXE generic bootdisk
tmpl = ForemanBootdisk::Renderer.new.generic_template_render
rescue StandardError => e
error_rendering(e)
Expand All @@ -20,13 +21,14 @@ def generic
end

ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl) do |iso|
send_data read_file(iso), filename: "bootdisk_#{URI.parse(Setting[:foreman_url]).host}.iso"
send_file(iso, filename: "bootdisk_#{URI.parse(Setting[:foreman_url]).host}.iso")
end
end

def host
host = @disk
begin
# EFI not supported for iPXE host bootdisk
tmpl = host.bootdisk_template_render
rescue StandardError => e
error_rendering(e)
Expand All @@ -35,14 +37,14 @@ def host
end

ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl) do |iso|
send_data read_file(iso), filename: "#{host.name}.iso"
send_file(iso, filename: "#{host.name}.iso")
end
end

def full_host
host = @disk
ForemanBootdisk::ISOGenerator.generate_full_host(host) do |iso|
send_data read_file(iso), filename: "#{host.name}#{ForemanBootdisk::ISOGenerator.token_expiry(host)}.iso"
send_file(iso, filename: "#{host.name}#{ForemanBootdisk::ISOGenerator.token_expiry(host)}.iso")
end
end

Expand All @@ -51,26 +53,25 @@ def subnet
begin
subnet = host.try(:subnet) || raise(::Foreman::Exception.new(N_('Subnet is not assigned to the host %s'), host.name))
subnet.tftp || raise(::Foreman::Exception.new(N_('TFTP feature not enabled for subnet %s'), subnet.name))
tmpl = ForemanBootdisk::Renderer.new.generic_template_render(subnet)
subnet.httpboot || ForemanBootdisk.logger.warn('HTTPBOOT feature is not enabled for subnet %s, UEFI may not be available for bootdisk' % subnet.name)

tmpl_bios = ForemanBootdisk::Renderer.new.generic_template_render(subnet)
tmpl_efi = ForemanBootdisk::Renderer.new.generic_efi_template_render(subnet)
rescue StandardError => e
error_rendering(e)
redirect_back(fallback_location: '/')
return
end

ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl) do |iso|
send_data read_file(iso), filename: "bootdisk_subnet_#{subnet.name}.iso"
ForemanBootdisk::ISOGenerator.generate(ipxe: tmpl_bios, grub: tmpl_efi) do |iso|
send_file(iso, filename: "bootdisk_subnet_#{subnet.name}.iso")
end
end

def help; end

private

def read_file(filename)
File.read(filename)
end

def resource_scope(_controller = controller_name)
Host::Managed.authorized(:view_hosts)
end
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/concerns/foreman_bootdisk/hosts_helper_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def bootdisk_button_disabled(host)

# need to wrap this one in a test for template proxy presence
def display_bootdisk_for_subnet(host)
if (proxy = host.try(:subnet).try(:tftp)) && proxy.has_feature?('Templates')
if (proxy = host.try(:subnet).try(:tftp) || host.try(:subnet).try(:httpboot)) && proxy.has_feature?('Templates')
display_bootdisk_link_if_authorized(
_("Subnet '%s' generic image") % host.subnet.name, {
controller: 'foreman_bootdisk/disks',
Expand Down
5 changes: 4 additions & 1 deletion app/lib/foreman_bootdisk/scope/bootdisk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ class Bootdisk < ::Foreman::Renderer::Scope::Provisioning
def bootdisk_chain_url(mac = host.try(:mac), action = 'iPXE')
url = foreman_url(action)
u = URI.parse(url)
ForemanBootdisk.logger.warn("Foreman or proxy is configured with HTTPS, probably not supported by iPXE: #{u}") if u.scheme == 'https'
new_query_data = URI.decode_www_form(u.query || '') << ['mac', mac || '']
new_querystring = URI.encode_www_form(new_query_data)
u.query = nil
Expand All @@ -18,6 +17,10 @@ def bootdisk_chain_url(mac = host.try(:mac), action = 'iPXE')
def bootdisk_raise(*args)
raise ::Foreman::Exception.new(*args)
end

def template_name
"Foreman Bootdisk"
end
end
end
end
15 changes: 15 additions & 0 deletions app/lib/foreman_bootdisk/scope/full_host_bootdisk_efi.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module ForemanBootdisk
module Scope
class FullHostBootdiskEfi < Bootdisk
def kernel(medium_provider)
'/' + ForemanBootdisk::ISOGenerator.iso9660_filename(super)
end

def initrd(medium_provider)
'/' + ForemanBootdisk::ISOGenerator.iso9660_filename(super)
end
end
end
end
9 changes: 3 additions & 6 deletions app/models/concerns/foreman_bootdisk/host_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
module ForemanBootdisk
module HostExt
def bootdisk_template
template = ProvisioningTemplate.unscoped.find_by(
name: Setting[:bootdisk_host_template]
)
template = ProvisioningTemplate.unscoped.find_by(name: Setting[:bootdisk_host_template])
unless template
raise ::Foreman::Exception.new(
N_('Unable to find template specified by %s setting'), 'bootdisk_host_template'
)
raise ::Foreman::Exception.new(N_('Unable to find template specified by %s setting'), 'bootdisk_host_template')
end

template
end

Expand Down
4 changes: 4 additions & 0 deletions app/models/setting/bootdisk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ def self.default_settings
ipxe = ['/usr/lib/ipxe'].find { |p| File.exist?(p) } || '/usr/share/ipxe'
isolinux = ['/usr/lib/ISOLINUX'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
syslinux = ['/usr/lib/syslinux/modules/bios', '/usr/lib/syslinux'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
grub2 = ['/var/lib/tftpboot/grub2'].find { |p| File.exist?(p) } || '/var/lib/foreman/bootdisk'
templates = -> { Hash[ProvisioningTemplate.where(template_kind: TemplateKind.where(name: 'Bootdisk')).map { |temp| [temp[:name], temp[:name]] }] }

[
set('bootdisk_ipxe_dir', N_('Path to directory containing iPXE images'), ipxe, N_('iPXE directory')),
set('bootdisk_isolinux_dir', N_('Path to directory containing isolinux images'), isolinux, N_('ISOLINUX directory')),
set('bootdisk_syslinux_dir', N_('Path to directory containing syslinux images'), syslinux, N_('SYSLINUX directory')),
set('bootdisk_grub2_dir', N_('Path to directory containing grubx64.efi and shimx64.efi'), grub2, N_('Grub2 directory')),
set('bootdisk_host_template', N_('iPXE template to use for host-specific boot disks'),
'Boot disk iPXE - host', N_('Host image template'), nil, collection: templates),
set('bootdisk_generic_host_template', N_('iPXE template to use for generic host boot disks'),
'Boot disk iPXE - generic host', N_('Generic image template'), nil, collection: templates),
set('bootdisk_generic_efi_host_template', N_('Grub2 template to use for generic EFI host boot disks'),
'Boot disk Grub2 EFI - generic host', N_('Generic Grub2 EFI image template'), nil, collection: templates),
set('bootdisk_mkiso_command', N_('Command to generate ISO image, use genisoimage or mkisofs'), 'genisoimage', N_('ISO generation command')),
set('bootdisk_cache_media', N_('Installation media files will be cached for full host images'), true, N_('Installation media caching'))
]
Expand Down
Loading

0 comments on commit 09dc92d

Please sign in to comment.