foreman_bootdisk 14.0.0 → 17.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AUTHORS +30 -0
- data/README.md +25 -0
- data/app/controllers/foreman_bootdisk/api/v2/disks_controller.rb +5 -7
- data/app/controllers/foreman_bootdisk/api/v2/subnet_disks_controller.rb +9 -4
- data/app/controllers/foreman_bootdisk/disks_controller.rb +11 -10
- data/app/helpers/concerns/foreman_bootdisk/hosts_helper_ext.rb +14 -14
- data/app/lib/foreman_bootdisk/scope/bootdisk.rb +4 -1
- data/app/lib/foreman_bootdisk/scope/full_host_bootdisk_efi.rb +15 -0
- data/app/models/concerns/foreman_bootdisk/compute_resources/vmware.rb +10 -1
- data/app/models/concerns/foreman_bootdisk/host_ext.rb +7 -10
- data/app/models/concerns/foreman_bootdisk/orchestration/compute.rb +28 -19
- data/app/models/setting/bootdisk.rb +16 -19
- data/app/services/foreman_bootdisk/iso_generator.rb +129 -52
- data/app/services/foreman_bootdisk/renderer.rb +36 -18
- data/app/views/foreman_bootdisk/generic_efi_host.erb +64 -0
- data/app/views/foreman_bootdisk/generic_static_host.erb +34 -0
- data/app/views/foreman_bootdisk/host.erb +27 -11
- data/db/seeds.d/50-bootdisk_templates.rb +15 -31
- data/lib/foreman_bootdisk/engine.rb +6 -6
- data/lib/foreman_bootdisk/version.rb +1 -1
- data/lib/tasks/bootdisk.rake +10 -6
- data/locale/action_names.rb +5 -0
- data/locale/ca/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ca/foreman_bootdisk.po +65 -16
- data/locale/de/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/de/foreman_bootdisk.po +74 -23
- data/locale/en/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/en/foreman_bootdisk.po +58 -10
- data/locale/en_GB/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/en_GB/foreman_bootdisk.po +65 -17
- data/locale/es/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/es/foreman_bootdisk.po +82 -34
- data/locale/foreman_bootdisk.pot +124 -48
- data/locale/fr/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/fr/foreman_bootdisk.po +65 -17
- data/locale/it/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/it/foreman_bootdisk.po +63 -15
- data/locale/ja/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ja/foreman_bootdisk.po +64 -16
- data/locale/ko/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ko/foreman_bootdisk.po +63 -15
- data/locale/pt_BR/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/pt_BR/foreman_bootdisk.po +76 -27
- data/locale/ru/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ru/foreman_bootdisk.po +63 -15
- data/locale/sv_SE/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/sv_SE/foreman_bootdisk.po +61 -13
- data/locale/zh_CN/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/zh_CN/foreman_bootdisk.po +79 -31
- data/locale/zh_TW/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/zh_TW/foreman_bootdisk.po +63 -15
- data/release-gem +84 -0
- data/test/functional/foreman_bootdisk/api/v2/disks_controller_test.rb +51 -17
- data/test/functional/foreman_bootdisk/api/v2/subnet_disks_controller_test.rb +23 -10
- data/test/functional/foreman_bootdisk/disks_controller_test.rb +65 -25
- data/test/test_plugin_helper.rb +23 -3
- data/test/unit/concerns/host_test.rb +12 -1
- data/test/unit/concerns/orchestration/compute_test.rb +32 -13
- data/test/unit/foreman_bootdisk/renderer_test.rb +1 -1
- data/test/unit/iso_generator_test.rb +16 -7
- metadata +65 -4
@@ -2,30 +2,27 @@
|
|
2
2
|
|
3
3
|
class Setting
|
4
4
|
class Bootdisk < ::Setting
|
5
|
-
def self.
|
6
|
-
return unless ApplicationRecord.connection.table_exists?('settings')
|
7
|
-
return unless super
|
8
|
-
|
5
|
+
def self.default_settings
|
9
6
|
ipxe = ['/usr/lib/ipxe'].find { |p| File.exist?(p) } || '/usr/share/ipxe'
|
10
7
|
isolinux = ['/usr/lib/ISOLINUX'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
|
11
8
|
syslinux = ['/usr/lib/syslinux/modules/bios', '/usr/lib/syslinux'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
|
9
|
+
grub2 = ['/var/lib/tftpboot/grub2'].find { |p| File.exist?(p) } || '/var/lib/foreman/bootdisk'
|
12
10
|
templates = -> { Hash[ProvisioningTemplate.where(template_kind: TemplateKind.where(name: 'Bootdisk')).map { |temp| [temp[:name], temp[:name]] }] }
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
true
|
12
|
+
[
|
13
|
+
set('bootdisk_ipxe_dir', N_('Path to directory containing iPXE images'), ipxe, N_('iPXE directory')),
|
14
|
+
set('bootdisk_isolinux_dir', N_('Path to directory containing isolinux images'), isolinux, N_('ISOLINUX directory')),
|
15
|
+
set('bootdisk_syslinux_dir', N_('Path to directory containing syslinux images'), syslinux, N_('SYSLINUX directory')),
|
16
|
+
set('bootdisk_grub2_dir', N_('Path to directory containing grubx64.efi and shimx64.efi'), grub2, N_('Grub2 directory')),
|
17
|
+
set('bootdisk_host_template', N_('iPXE template to use for host-specific boot disks'),
|
18
|
+
'Boot disk iPXE - host', N_('Host image template'), nil, collection: templates),
|
19
|
+
set('bootdisk_generic_host_template', N_('iPXE template to use for generic host boot disks'),
|
20
|
+
'Boot disk iPXE - generic host', N_('Generic image template'), nil, collection: templates),
|
21
|
+
set('bootdisk_generic_efi_host_template', N_('Grub2 template to use for generic EFI host boot disks'),
|
22
|
+
'Boot disk Grub2 EFI - generic host', N_('Generic Grub2 EFI image template'), nil, collection: templates),
|
23
|
+
set('bootdisk_mkiso_command', N_('Command to generate ISO image, use genisoimage or mkisofs'), 'genisoimage', N_('ISO generation command')),
|
24
|
+
set('bootdisk_cache_media', N_('Installation media files will be cached for full host images'), true, N_('Installation media caching'))
|
25
|
+
]
|
29
26
|
end
|
30
27
|
|
31
28
|
def self.humanized_category
|
@@ -11,9 +11,10 @@ require 'uri'
|
|
11
11
|
module ForemanBootdisk
|
12
12
|
class ISOGenerator
|
13
13
|
def self.generate_full_host(host, opts = {}, &block)
|
14
|
-
raise Foreman::Exception
|
14
|
+
raise Foreman::Exception.new(N_('Host is not in build mode, so the template cannot be rendered')) unless host.build?
|
15
15
|
|
16
|
-
|
16
|
+
isolinux_template = render_template(host, :PXELinux, ForemanBootdisk::Scope::FullHostBootdisk)
|
17
|
+
grub_template = render_template(host, :PXEGrub2, ForemanBootdisk::Scope::FullHostBootdiskEfi)
|
17
18
|
|
18
19
|
# pxe_files and filename conversion is utterly bizarre
|
19
20
|
# aim to convert filenames to something usable under ISO 9660, to match as rendered in the template
|
@@ -24,84 +25,145 @@ module ForemanBootdisk
|
|
24
25
|
hash[iso_filename] = host.url_for_boot(type)
|
25
26
|
end
|
26
27
|
|
27
|
-
generate(opts.merge(isolinux:
|
28
|
+
generate(opts.merge(isolinux: isolinux_template, grub: grub_template, files: files), &block)
|
29
|
+
rescue ::Foreman::Exception => e
|
30
|
+
if e.code == 'ERF42-0067'
|
31
|
+
ForemanBootdisk.logger.warn e
|
32
|
+
else
|
33
|
+
raise e
|
34
|
+
end
|
28
35
|
end
|
29
36
|
|
30
|
-
def self.
|
31
|
-
|
37
|
+
def self.render_template(host, kind, scope_class)
|
38
|
+
template = host.provisioning_template(kind: kind)
|
32
39
|
|
33
|
-
raise Foreman::Exception
|
40
|
+
raise Foreman::Exception.new(N_('Unable to generate disk template, %{kind} template not found.'), kind: kind) unless template
|
34
41
|
|
35
42
|
template = ForemanBootdisk::Renderer.new.render_template(
|
36
|
-
template:
|
43
|
+
template: template,
|
37
44
|
host: host,
|
38
|
-
scope_class:
|
45
|
+
scope_class: scope_class
|
39
46
|
)
|
40
47
|
|
41
48
|
unless template
|
42
49
|
err = host.errors.full_messages.to_sentence
|
43
|
-
raise
|
50
|
+
raise Foreman::Exception.new(N_('Unable to generate disk %{kind} template: %{error}'), kind: kind, error: err)
|
44
51
|
end
|
45
52
|
|
46
53
|
template
|
47
54
|
end
|
48
55
|
|
56
|
+
def self.system_or_exception(command, error)
|
57
|
+
unless system(command)
|
58
|
+
ForemanBootdisk.logger.debug "Bootdisk command failed: #{command}"
|
59
|
+
raise Foreman::Exception.new(N_(error))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
49
63
|
def self.generate(opts = {})
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
64
|
+
# isolinux template not provided for generic BIOS bootdisks
|
65
|
+
if opts[:isolinux].nil? && opts[:ipxe]
|
66
|
+
opts[:isolinux] = <<~EOT
|
67
|
+
default ipxe
|
68
|
+
label ipxe
|
69
|
+
kernel /ipxe
|
70
|
+
initrd /script
|
71
|
+
EOT
|
72
|
+
end
|
56
73
|
|
57
|
-
|
58
|
-
|
74
|
+
if opts[:grub].nil? && opts[:ipxe]
|
75
|
+
opts[:grub] = <<~EOT
|
76
|
+
echo "Grub2 template not associated and/or unsupported bootdisk type."
|
77
|
+
echo "The following bootdisks are supported for EFI systems:"
|
78
|
+
echo " * FULL HOST BOOTDISK"
|
79
|
+
echo " * SUBNET GENERIC BOOTDISK"
|
80
|
+
echo "The system will poweroff in few minutes..."
|
81
|
+
sleep 500
|
82
|
+
poweroff
|
83
|
+
EOT
|
84
|
+
end
|
59
85
|
|
60
|
-
|
61
|
-
|
62
|
-
|
86
|
+
# Temporary directory cannot be cleaned inprocess due to send_file offloaded to web server
|
87
|
+
wd = Dir.mktmpdir('bootdisk-iso-')
|
88
|
+
Dir.mkdir(File.join(wd, 'build'))
|
63
89
|
|
64
|
-
|
90
|
+
if opts[:isolinux]
|
91
|
+
isolinux_source_file = File.join(Setting[:bootdisk_isolinux_dir], 'isolinux.bin')
|
92
|
+
raise Foreman::Exception.new(N_('Please ensure the isolinux/syslinux package(s) are installed.')) unless File.exist?(isolinux_source_file)
|
65
93
|
|
66
|
-
|
67
|
-
FileUtils.cp(ldlinux_source_file, File.join(wd, 'build', 'ldlinux.c32')) if File.exist?(ldlinux_source_file)
|
94
|
+
FileUtils.cp(isolinux_source_file, File.join(wd, 'build', 'isolinux.bin'))
|
68
95
|
|
69
|
-
|
70
|
-
|
71
|
-
|
96
|
+
source_files = ['ldlinux.c32', 'menu.c32', 'libutil.c32']
|
97
|
+
source_files.each do |source_file|
|
98
|
+
full_path = File.join(Setting[:bootdisk_syslinux_dir], source_file)
|
99
|
+
FileUtils.cp(full_path, File.join(wd, 'build', source_file)) if File.exist?(full_path)
|
100
|
+
end
|
101
|
+
|
102
|
+
File.open(File.join(wd, 'build', 'isolinux.cfg'), 'w') do |file|
|
103
|
+
file.write(opts[:isolinux])
|
72
104
|
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if opts[:ipxe]
|
108
|
+
ipxe_source_file = File.join(Setting[:bootdisk_ipxe_dir], 'ipxe.lkrn')
|
109
|
+
raise Foreman::Exception.new(N_('Please ensure the ipxe-bootimgs package is installed.')) unless File.exist?(ipxe_source_file)
|
73
110
|
|
74
|
-
|
75
|
-
|
76
|
-
|
111
|
+
FileUtils.cp(ipxe_source_file, File.join(wd, 'build', 'ipxe'))
|
112
|
+
File.open(File.join(wd, 'build', 'script'), 'w') { |file| file.write(opts[:ipxe]) }
|
113
|
+
end
|
77
114
|
|
78
|
-
|
79
|
-
|
115
|
+
if opts[:grub]
|
116
|
+
FileUtils.mkdir_p(File.join(wd, 'build', 'EFI', 'BOOT'))
|
117
|
+
# a copy when using CDROM directly
|
118
|
+
File.open(File.join(wd, 'build', 'EFI', 'BOOT', 'grub.cfg'), 'w') { |file| file.write(opts[:grub]) }
|
119
|
+
# a copy when using USB/HDD (copied into EFI image as well)
|
120
|
+
File.open(File.join(wd, 'build', 'grub-hdd.cfg'), 'w') do |f|
|
121
|
+
# set root to (cd0) or similar when booting via disk
|
122
|
+
f.write("search --file /ISOLINUX.BIN --set root\n")
|
123
|
+
f.write(opts[:grub])
|
124
|
+
end
|
125
|
+
efibootimg = File.join(wd, 'build', 'efiboot.img')
|
126
|
+
system_or_exception("truncate -s 4M #{efibootimg}", N_('Creating new image failed, install truncate utility'))
|
127
|
+
system_or_exception("mkfs.msdos #{efibootimg}", N_('Failed to format the ESP image via mkfs.msdos'))
|
128
|
+
system_or_exception("mmd -i #{efibootimg} '::/EFI'", N_('Failed to create a directory within the ESP image'))
|
129
|
+
system_or_exception("mmd -i #{efibootimg} '::/EFI/BOOT'", N_('Failed to create a directory within the ESP image'))
|
130
|
+
{
|
131
|
+
File.join(wd, 'build', 'grub-hdd.cfg').to_s => 'GRUB.CFG',
|
132
|
+
File.join(Setting[:bootdisk_grub2_dir], 'grubx64.efi').to_s => 'GRUBX64.EFI',
|
133
|
+
File.join(Setting[:bootdisk_grub2_dir], 'shimx64.efi').to_s => 'BOOTX64.EFI',
|
134
|
+
}.each do |src, dest|
|
135
|
+
raise(Foreman::Exception.new(N_('Ensure %{path} contains grubx64.efi and shimx64.efi: install TFTP module or copy those files into /var/lib/foreman/bootdisk (Grub2 directory setting)'), path: src)) unless File.exist?(src)
|
136
|
+
raise(Foreman::Exception.new(N_('Unable to mcopy %{path}'), path: src)) unless system("mcopy -m -i #{efibootimg} '#{src}' '#{"::/EFI/BOOT/#{dest}"}'")
|
80
137
|
end
|
138
|
+
mkiso_args = "-eltorito-alt-boot -e efiboot.img -no-emul-boot"
|
139
|
+
isohybrod_args = ["--uefi"]
|
140
|
+
else
|
141
|
+
mkiso_args = ''
|
142
|
+
isohybrod_args = []
|
143
|
+
end
|
81
144
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
145
|
+
if opts[:files]
|
146
|
+
if opts[:files].respond_to?(:each)
|
147
|
+
opts[:files].each do |file, source|
|
148
|
+
fetch(File.join(wd, 'build', file), source)
|
87
149
|
end
|
88
150
|
end
|
151
|
+
end
|
89
152
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
153
|
+
iso = if opts[:dir]
|
154
|
+
Tempfile.new(['bootdisk', '.iso'], opts[:dir]).path
|
155
|
+
else
|
156
|
+
File.join(wd, 'output.iso')
|
157
|
+
end
|
158
|
+
raise Foreman::Exception.new(N_('ISO build failed')) unless system(build_mkiso_command(output_file: iso, extra_commands: mkiso_args, source_directory: File.join(wd, 'build')))
|
96
159
|
|
97
|
-
|
98
|
-
|
160
|
+
# Make the ISO bootable as a HDD/USB disk too
|
161
|
+
raise Foreman::Exception.new(N_('ISO hybrid conversion failed: %s'), $?) unless system(*["isohybrid", isohybrod_args, iso].flatten.compact)
|
99
162
|
|
100
|
-
|
101
|
-
end
|
163
|
+
yield iso
|
102
164
|
end
|
103
165
|
|
104
|
-
def self.build_mkiso_command(output_file:, source_directory:)
|
166
|
+
def self.build_mkiso_command(output_file:, source_directory:, extra_commands:)
|
105
167
|
arguments = [
|
106
168
|
"-o #{output_file}",
|
107
169
|
'-iso-level 2',
|
@@ -111,6 +173,7 @@ module ForemanBootdisk
|
|
111
173
|
'-boot-load-size 4',
|
112
174
|
'-boot-info-table'
|
113
175
|
]
|
176
|
+
arguments.push(extra_commands) unless extra_commands.nil?
|
114
177
|
[Setting[:bootdisk_mkiso_command], arguments, source_directory].flatten.join(' ')
|
115
178
|
end
|
116
179
|
|
@@ -121,7 +184,7 @@ module ForemanBootdisk
|
|
121
184
|
'_' + expiry.strftime('%Y%m%d_%H%M')
|
122
185
|
end
|
123
186
|
|
124
|
-
def self.fetch(path, uri)
|
187
|
+
def self.fetch(path, uri, limit = 10)
|
125
188
|
dir = File.dirname(path)
|
126
189
|
FileUtils.mkdir_p(dir) unless File.exist?(dir)
|
127
190
|
|
@@ -138,11 +201,22 @@ module ForemanBootdisk
|
|
138
201
|
write_cache = use_cache
|
139
202
|
uri = URI(uri)
|
140
203
|
Net::HTTP.start(uri.host, uri.port) do |http|
|
141
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
204
|
+
request = Net::HTTP::Get.new(uri.request_uri, 'Accept-Encoding' => 'plain')
|
142
205
|
|
143
206
|
http.request(request) do |response|
|
144
|
-
response
|
145
|
-
|
207
|
+
case response
|
208
|
+
when Net::HTTPSuccess then
|
209
|
+
response.read_body do |chunk|
|
210
|
+
file.write chunk
|
211
|
+
end
|
212
|
+
when Net::HTTPRedirection then
|
213
|
+
raise("Too many HTTP redirects when downloading #{uri}") if limit <= 0
|
214
|
+
|
215
|
+
fetch(path, response['location'], limit - 1)
|
216
|
+
# prevent multiple writes to the cache
|
217
|
+
write_cache = false
|
218
|
+
else
|
219
|
+
raise ::Foreman::Exception, N_(format("Unable to download boot file %{uri}, HTTP return code %{code}", uri: uri, code: response.code))
|
146
220
|
end
|
147
221
|
end
|
148
222
|
end
|
@@ -151,8 +225,11 @@ module ForemanBootdisk
|
|
151
225
|
|
152
226
|
return unless write_cache
|
153
227
|
|
228
|
+
contents = File.read(path)
|
229
|
+
return if contents.empty?
|
230
|
+
|
154
231
|
ForemanBootdisk.logger.debug("Caching contents of #{uri}")
|
155
|
-
Rails.cache.write(uri,
|
232
|
+
Rails.cache.write(uri, contents, raw: true)
|
156
233
|
end
|
157
234
|
|
158
235
|
# isolinux supports up to ISO 9660 level 2 filenames
|
@@ -4,35 +4,46 @@ require 'uri'
|
|
4
4
|
|
5
5
|
module ForemanBootdisk
|
6
6
|
class Renderer
|
7
|
-
def
|
8
|
-
host = if subnet.present?
|
9
|
-
# rendering a subnet-level bootdisk requires tricking the renderer into thinking it has a
|
10
|
-
# valid host, without a token, but with a tftp proxy
|
11
|
-
Struct.new(:token, :provision_interface).new(
|
12
|
-
nil,
|
13
|
-
Struct.new(:subnet).new(subnet)
|
14
|
-
)
|
15
|
-
else
|
16
|
-
Struct.new(:token, :subnet).new(nil, nil)
|
17
|
-
end
|
18
|
-
|
19
|
-
render_template(template: generic_host_template, host: host)
|
20
|
-
end
|
21
|
-
|
22
|
-
def render_template(template:, host:, scope_class: renderer_scope)
|
7
|
+
def render_template(template:, host:, scope_class: renderer_scope, subnet: nil)
|
23
8
|
source = Foreman::Renderer.get_source(
|
24
9
|
template: template,
|
25
|
-
host: host
|
26
10
|
)
|
27
11
|
scope = Foreman::Renderer.get_scope(
|
28
12
|
host: host,
|
29
|
-
|
13
|
+
variables: { subnet: subnet, bootdisk: true },
|
14
|
+
klass: scope_class,
|
30
15
|
)
|
31
16
|
Foreman::Renderer.render(source, scope)
|
32
17
|
end
|
33
18
|
|
19
|
+
def generic_template_render(subnet = nil)
|
20
|
+
render_template(template: generic_host_template, host: stub_host(subnet), subnet: subnet)
|
21
|
+
end
|
22
|
+
|
23
|
+
def generic_efi_template_render(subnet)
|
24
|
+
if subnet.httpboot?
|
25
|
+
render_template(template: generic_efi_host_template, host: stub_host(subnet), subnet: subnet)
|
26
|
+
else
|
27
|
+
ForemanBootdisk.logger.warn('HTTPBOOT feature is not enabled for subnet %s, UEFI may not be available for bootdisk' % subnet.name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
34
31
|
private
|
35
32
|
|
33
|
+
def stub_host(subnet)
|
34
|
+
if subnet.present?
|
35
|
+
# rendering a subnet-level bootdisk requires tricking the renderer into thinking it has a
|
36
|
+
# valid host, without a token, but with a tftp proxy
|
37
|
+
Struct.new(:token, :provision_interface, :content_source).new(
|
38
|
+
nil,
|
39
|
+
Struct.new(:subnet).new(subnet),
|
40
|
+
nil
|
41
|
+
)
|
42
|
+
else
|
43
|
+
Struct.new(:token, :subnet, :content_source).new(nil, nil, nil)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
36
47
|
def renderer_scope
|
37
48
|
ForemanBootdisk::Scope::Bootdisk
|
38
49
|
end
|
@@ -43,5 +54,12 @@ module ForemanBootdisk
|
|
43
54
|
|
44
55
|
template
|
45
56
|
end
|
57
|
+
|
58
|
+
def generic_efi_host_template
|
59
|
+
template = ProvisioningTemplate.unscoped.find_by(name: Setting[:bootdisk_generic_efi_host_template])
|
60
|
+
raise ::Foreman::Exception.new(N_('Unable to find template specified by %s setting'), 'bootdisk_generic_efi_host_template') unless template
|
61
|
+
|
62
|
+
template
|
63
|
+
end
|
46
64
|
end
|
47
65
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# Boot disk Grub2 EFI - generic host
|
3
|
+
#
|
4
|
+
#set debug="http,efinet,net"
|
5
|
+
#set debug=all
|
6
|
+
echo "Foreman Bootdisk: 'Boot disk Grub2 EFI - generic host' template"
|
7
|
+
echo
|
8
|
+
echo "********************************************************"
|
9
|
+
echo " REQUIREMENTS:"
|
10
|
+
echo " * SUBNET GENERIC IMAGE ONLY (host image not supported)"
|
11
|
+
echo " * HOST PARAM default_grub_install_entry set to efi_http"
|
12
|
+
echo " * PROXY WITH HTTPBOOT FEATURE"
|
13
|
+
echo " * HTTP UEFI BOOT ONLY (Legacy/PXE not supported)"
|
14
|
+
echo " * IPv4 ONLY (IPv6 not tested, change the template)"
|
15
|
+
echo " * HTTP ONLY (change the template for HTTPS)"
|
16
|
+
echo " * ISC DHCP (other servers not tested)"
|
17
|
+
echo " * GRUB FROM RHEL 8.3+/7.9+ (when generating the image)"
|
18
|
+
echo " * EFI HTTP or HTTPS grub entry must be selected in menu"
|
19
|
+
echo " * DNS must resolve proxy hostname via DNS proxy if set"
|
20
|
+
echo "*******************************************************"
|
21
|
+
sleep 5
|
22
|
+
<%
|
23
|
+
# possible values are: "http" or "https"
|
24
|
+
proxy_proto = "http"
|
25
|
+
|
26
|
+
@subnet || bootdisk_raise("Generic disk not supported for EFI, use subnet disk")
|
27
|
+
@subnet.template? || bootdisk_raise("Requires a proxy with template feature")
|
28
|
+
proxy_port = if proxy_proto == "http"
|
29
|
+
@subnet.httpboot.httpboot_http_port
|
30
|
+
else
|
31
|
+
@subnet.httpboot.httpboot_https_port
|
32
|
+
end
|
33
|
+
# Workaround for "no DNS server configured" https://bugzilla.redhat.com/show_bug.cgi?id=1842509
|
34
|
+
proxy_httpboot_host = dns_lookup(@subnet.httpboot.hostname)
|
35
|
+
proxy_template_host = dns_lookup(@subnet.template.hostname)
|
36
|
+
-%>
|
37
|
+
echo
|
38
|
+
net_ls_cards
|
39
|
+
echo "Configuring ALL cards via BOOTP/IPv4"
|
40
|
+
net_bootp
|
41
|
+
# uncomment here for IPv6 support (not tested)
|
42
|
+
#echo "Configuring ALL cards via BOOTP/IPv6"
|
43
|
+
#net_ipv6_autoconf
|
44
|
+
net_ls_addr
|
45
|
+
net_ls_routes
|
46
|
+
net_ls_dns
|
47
|
+
sleep 5
|
48
|
+
set root=(<%= proxy_proto %>,<%= proxy_httpboot_host %>:<%= proxy_port %>)
|
49
|
+
# The variable will not survive configfile fetch, therefore absolute path
|
50
|
+
# must be used in the chainloaded template.
|
51
|
+
# https://bugzilla.redhat.com/show_bug.cgi?id=1842893
|
52
|
+
set http_path=/httpboot/
|
53
|
+
set default=efi_<%= proxy_proto %>
|
54
|
+
<% (0..32).each do |i| -%>
|
55
|
+
echo "Trying efinet<%= i %> via <%= proxy_proto %>://<%= proxy_template_host %>:<%= proxy_port %>/unattended/PXEGrub2?mac=$net_efinet<%= i %>_dhcp_mac"
|
56
|
+
set net_default_mac=$net_efinet<%= i %>_dhcp_mac
|
57
|
+
sleep 5
|
58
|
+
configfile (<%= proxy_proto %>,<%= proxy_template_host %>:<%= proxy_port %>)/unattended/PXEGrub2?mac=$net_efinet<%= i %>_dhcp_mac
|
59
|
+
<% end -%>
|
60
|
+
|
61
|
+
echo "Could not find a host with PXEGrub2 template and one of the MAC addresses!"
|
62
|
+
echo "The system will poweroff in few minutes..."
|
63
|
+
sleep 500
|
64
|
+
poweroff
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!ipxe
|
2
|
+
#
|
3
|
+
# Generic host template with interactive static IP configuration. Tokens
|
4
|
+
# must be disabled in order to access templates via MAC addresses.
|
5
|
+
#
|
6
|
+
|
7
|
+
<% (0..32).each do |i| -%>
|
8
|
+
:net<%= i %>
|
9
|
+
isset ${net<%= i -%>/mac} || goto configure
|
10
|
+
echo Found ${net<%= i -%>/mac} as net<%= i -%> on a ${net<%= i -%>/chip}
|
11
|
+
goto net<%= i+1 %>
|
12
|
+
<% end -%>
|
13
|
+
|
14
|
+
:configure
|
15
|
+
echo -n Interface (e.g. net0): && read interface
|
16
|
+
iseq ${interface} n && goto reboot ||
|
17
|
+
iseq ${interface} N && goto reboot ||
|
18
|
+
|
19
|
+
ifopen ${interface}
|
20
|
+
echo Please enter IPv4 details for ${interface}
|
21
|
+
echo
|
22
|
+
|
23
|
+
echo -n IP address: && read ${interface}/ip
|
24
|
+
echo -n Subnet mask: && read ${interface}/netmask
|
25
|
+
echo -n Default gateway: && read ${interface}/gateway
|
26
|
+
echo -n DNS server: && read dns
|
27
|
+
|
28
|
+
chain <%= bootdisk_chain_url %>${${interface}/mac} || goto reboot
|
29
|
+
exit 0
|
30
|
+
|
31
|
+
:reboot
|
32
|
+
echo Unable to continue, rebooting...
|
33
|
+
sleep 30
|
34
|
+
exit 1
|