foreman_bootdisk 13.0.0 → 16.1.0

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS +29 -0
  3. data/CHANGES.md +4 -0
  4. data/README.md +19 -2
  5. data/app/controllers/foreman_bootdisk/api/v2/disks_controller.rb +11 -9
  6. data/app/controllers/foreman_bootdisk/api/v2/subnet_disks_controller.rb +37 -31
  7. data/app/controllers/foreman_bootdisk/disks_controller.rb +20 -19
  8. data/app/helpers/concerns/foreman_bootdisk/hosts_helper_ext.rb +86 -45
  9. data/app/lib/foreman_bootdisk/scope/bootdisk.rb +2 -0
  10. data/app/lib/foreman_bootdisk/scope/full_host_bootdisk.rb +15 -0
  11. data/app/models/concerns/foreman_bootdisk/compute_resources/vmware.rb +4 -2
  12. data/app/models/concerns/foreman_bootdisk/host_ext.rb +42 -30
  13. data/app/models/concerns/foreman_bootdisk/orchestration/compute.rb +14 -10
  14. data/app/models/setting/bootdisk.rb +21 -23
  15. data/app/services/foreman_bootdisk/iso_generator.rb +144 -104
  16. data/app/services/foreman_bootdisk/renderer.rb +17 -13
  17. data/app/views/foreman_bootdisk/generic_static_host.erb +34 -0
  18. data/app/views/foreman_bootdisk/host.erb +27 -11
  19. data/config/routes.rb +15 -13
  20. data/config/routes/mount_engine.rb +3 -1
  21. data/db/migrate/20130914211030_create_host_bootdisk_template.rb +4 -4
  22. data/db/migrate/20130915104500_edit_host_bootdisk_template_multinic.rb +4 -4
  23. data/db/migrate/20130915133321_create_kickstart_bootdisk_template.rb +4 -4
  24. data/db/migrate/20130915201457_create_generic_host_bootdisk_template.rb +4 -4
  25. data/db/migrate/20131021095100_edit_host_bootdisk_template_dns_secondary.rb +4 -4
  26. data/db/migrate/20140522185700_change_templatekind_to_bootdisk.rb +16 -14
  27. data/db/migrate/20171009225200_remove_duplicate_bootdisk_templates.rb +4 -2
  28. data/db/seeds.d/50-bootdisk_templates.rb +21 -36
  29. data/lib/foreman_bootdisk.rb +2 -0
  30. data/lib/foreman_bootdisk/engine.rb +26 -37
  31. data/lib/foreman_bootdisk/version.rb +3 -1
  32. data/lib/tasks/bootdisk.rake +34 -17
  33. data/locale/ca/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  34. data/locale/ca/foreman_bootdisk.po +31 -15
  35. data/locale/de/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  36. data/locale/de/foreman_bootdisk.po +39 -21
  37. data/locale/en/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  38. data/locale/en/foreman_bootdisk.po +24 -9
  39. data/locale/en_GB/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  40. data/locale/en_GB/foreman_bootdisk.po +30 -15
  41. data/locale/es/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  42. data/locale/es/foreman_bootdisk.po +48 -33
  43. data/locale/foreman_bootdisk.pot +80 -52
  44. data/locale/fr/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  45. data/locale/fr/foreman_bootdisk.po +30 -15
  46. data/locale/gemspec.rb +3 -1
  47. data/locale/it/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  48. data/locale/it/foreman_bootdisk.po +28 -13
  49. data/locale/ja/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  50. data/locale/ja/foreman_bootdisk.po +29 -14
  51. data/locale/ko/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  52. data/locale/ko/foreman_bootdisk.po +28 -13
  53. data/locale/pt_BR/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  54. data/locale/pt_BR/foreman_bootdisk.po +42 -26
  55. data/locale/ru/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  56. data/locale/ru/foreman_bootdisk.po +28 -13
  57. data/locale/sv_SE/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  58. data/locale/sv_SE/foreman_bootdisk.po +26 -11
  59. data/locale/zh_CN/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  60. data/locale/zh_CN/foreman_bootdisk.po +46 -31
  61. data/locale/zh_TW/LC_MESSAGES/foreman_bootdisk.mo +0 -0
  62. data/locale/zh_TW/foreman_bootdisk.po +28 -13
  63. data/release-gem +84 -0
  64. data/test/functional/foreman_bootdisk/api/v2/disks_controller_test.rb +35 -33
  65. data/test/functional/foreman_bootdisk/api/v2/subnet_disks_controller_test.rb +9 -7
  66. data/test/functional/foreman_bootdisk/disks_controller_test.rb +27 -25
  67. data/test/models/host/managed_test.rb +17 -13
  68. data/test/test_plugin_helper.rb +11 -7
  69. data/test/unit/access_permissions_test.rb +2 -0
  70. data/test/unit/concerns/compute_resources/vmware_test.rb +67 -63
  71. data/test/unit/concerns/host_test.rb +64 -53
  72. data/test/unit/concerns/orchestration/compute_test.rb +41 -39
  73. data/test/unit/foreman_bootdisk/renderer_test.rb +3 -1
  74. data/test/unit/foreman_bootdisk/scope/bootdisk_test.rb +3 -1
  75. data/test/unit/foreman_bootdisk/scope/full_host_bootdisk_test.rb +30 -0
  76. data/test/unit/iso_generator_test.rb +67 -40
  77. metadata +65 -5
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanBootdisk
2
4
  module Scope
3
5
  class Bootdisk < ::Foreman::Renderer::Scope::Provisioning
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanBootdisk
4
+ module Scope
5
+ class FullHostBootdisk < Bootdisk
6
+ def kernel(medium_provider)
7
+ ForemanBootdisk::ISOGenerator.iso9660_filename(super)
8
+ end
9
+
10
+ def initrd(medium_provider)
11
+ ForemanBootdisk::ISOGenerator.iso9660_filename(super)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanBootdisk
2
4
  module ComputeResources
3
5
  module Vmware
@@ -6,10 +8,10 @@ module ForemanBootdisk
6
8
  end
7
9
 
8
10
  def parse_args(args = {})
9
- args = super
11
+ args = super(args)
10
12
  if args[:provision_method] == 'bootdisk'
11
13
  args[:cdroms] = [new_cdrom]
12
- args[:boot_order] = ['cdrom', 'disk']
14
+ args[:boot_order] = %w[cdrom disk]
13
15
  args[:boot_retry] = 10
14
16
  end
15
17
  args
@@ -1,35 +1,47 @@
1
- require 'uri'
2
-
3
- module ForemanBootdisk::HostExt
4
- def bootdisk_template
5
- ProvisioningTemplate.unscoped.find_by_name(Setting[:bootdisk_host_template]) || raise(::Foreman::Exception.new(N_('Unable to find template specified by %s setting'), 'bootdisk_host_template'))
6
- end
7
-
8
- def bootdisk_template_render
9
- ForemanBootdisk::Renderer.new.render_template(template: bootdisk_template, host: self)
10
- end
11
-
12
- def bootdisk_build?
13
- provision_method == 'bootdisk'
14
- end
1
+ # frozen_string_literal: true
15
2
 
16
- def bootdisk?
17
- managed? && bootdisk_build? && SETTINGS[:unattended]
18
- end
19
-
20
- def bootdisk_downloadable?
21
- architecture.blank? || intel_arch?
22
- end
23
-
24
- def intel_arch?
25
- /i.86|x86[_-]64/ =~ architecture.name
26
- end
3
+ require 'uri'
27
4
 
28
- def validate_media?
29
- super || (managed && bootdisk_build? && build?)
5
+ module ForemanBootdisk
6
+ module HostExt
7
+ def bootdisk_template
8
+ template = ProvisioningTemplate.unscoped.find_by(
9
+ name: Setting[:bootdisk_host_template]
10
+ )
11
+ unless template
12
+ raise ::Foreman::Exception.new(
13
+ N_('Unable to find template specified by %s setting'), 'bootdisk_host_template'
14
+ )
15
+ end
16
+ template
17
+ end
18
+
19
+ def bootdisk_template_render
20
+ ForemanBootdisk::Renderer.new.render_template(template: bootdisk_template, host: self)
21
+ end
22
+
23
+ def bootdisk_build?
24
+ provision_method == 'bootdisk'
25
+ end
26
+
27
+ def bootdisk?
28
+ managed? && bootdisk_build? && SETTINGS[:unattended]
29
+ end
30
+
31
+ def bootdisk_downloadable?
32
+ architecture.blank? || intel_arch?
33
+ end
34
+
35
+ def intel_arch?
36
+ /i.86|x86[_-]64/ =~ architecture.name
37
+ end
38
+
39
+ def can_be_built?
40
+ super || (managed? && SETTINGS[:unattended] && bootdisk_build? && !build?)
41
+ end
30
42
  end
43
+ end
31
44
 
32
- def can_be_built?
33
- super || (managed? and SETTINGS[:unattended] and bootdisk_build? and !build?)
34
- end
45
+ class Host::Managed::Jail < Safemode::Jail
46
+ allow :bootdisk_build?
35
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tmpdir'
2
4
 
3
5
  module ForemanBootdisk
@@ -21,6 +23,7 @@ module ForemanBootdisk
21
23
  def queue_bootdisk_compute
22
24
  return unless compute? && errors.empty? && new_record?
23
25
  return unless provision_method == 'bootdisk'
26
+
24
27
  queue.create(name: _('Generating ISO image for %s') % self, priority: 5,
25
28
  action: [self, :setGenerateIsoImage])
26
29
  queue.create(name: _('Upload ISO image to datastore for %s') % self, priority: 6,
@@ -44,10 +47,10 @@ module ForemanBootdisk
44
47
  end
45
48
 
46
49
  def setGenerateIsoImage
47
- logger.info 'Generating ISO image for %s' % name
50
+ logger.info format('Generating ISO image for %s', name)
48
51
  bootdisk_generate_iso_image
49
- rescue => e
50
- failure _('Failed to generate ISO image for instance %{name}: %{message}') % { name: name, message: e.message }, e
52
+ rescue StandardError => e
53
+ failure format(_('Failed to generate ISO image for instance %{name}: %{message}'), name: name, message: e.message), e
51
54
  end
52
55
 
53
56
  def delGenerateIsoImage; end
@@ -55,29 +58,30 @@ module ForemanBootdisk
55
58
  def setIsoImage
56
59
  logger.info "Uploading ISO image #{bootdisk_isofile} for #{name}"
57
60
  bootdisk_upload_iso
58
- rescue => e
59
- failure _('Failed to upload ISO image for instance %{name}: %{message}') % { name: name, message: e.message }, e
61
+ rescue StandardError => e
62
+ failure format(_('Failed to upload ISO image for instance %{name}: %{message}'), name: name, message: e.message), e
60
63
  end
61
64
 
62
65
  def delIsoImage; end
63
66
 
64
67
  def setAttachIsoImage
65
- logger.info 'Attaching ISO image to CDROM drive for %s' % name
68
+ logger.info format('Attaching ISO image to CDROM drive for %s', name)
66
69
  bootdisk_attach_iso
67
- rescue => e
68
- failure _('Failed to attach ISO image to CDROM drive of instance %{name}: %{message}') % { name: name, message: e.message }, e
70
+ rescue StandardError => e
71
+ failure format(_('Failed to attach ISO image to CDROM drive of instance %{name}: %{message}'), name: name, message: e.message), e
69
72
  end
70
73
 
71
74
  def delAttachIsoImage; end
72
75
 
73
76
  def rebuild_with_bootdisk
74
77
  return true unless bootdisk?
78
+
75
79
  begin
76
80
  bootdisk_generate_iso_image
77
81
  bootdisk_upload_iso
78
82
  bootdisk_attach_iso
79
- rescue => e
80
- Foreman::Logging.exception "Failed to rebuild Bootdisk image for #{name}", e, :level => :error
83
+ rescue StandardError => e
84
+ Foreman::Logging.exception "Failed to rebuild Bootdisk image for #{name}", e, level: :error
81
85
  return false
82
86
  end
83
87
  end
@@ -1,30 +1,28 @@
1
- class Setting::Bootdisk< ::Setting
2
- def self.load_defaults
3
- return unless ApplicationRecord.connection.table_exists?('settings')
4
- return unless super
1
+ # frozen_string_literal: true
5
2
 
6
- ipxe = ['/usr/lib/ipxe'].find { |p| File.exist?(p) } || '/usr/share/ipxe'
7
- isolinux = ['/usr/lib/ISOLINUX'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
8
- syslinux = ['/usr/lib/syslinux/modules/bios', '/usr/lib/syslinux'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
9
- templates = -> { Hash[ProvisioningTemplate.where(:template_kind => TemplateKind.where(:name => 'Bootdisk')).map{|temp| [temp[:name], temp[:name]]}] }
3
+ class Setting
4
+ class Bootdisk < ::Setting
5
+ def self.default_settings
6
+ ipxe = ['/usr/lib/ipxe'].find { |p| File.exist?(p) } || '/usr/share/ipxe'
7
+ isolinux = ['/usr/lib/ISOLINUX'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
8
+ syslinux = ['/usr/lib/syslinux/modules/bios', '/usr/lib/syslinux'].find { |p| File.exist?(p) } || '/usr/share/syslinux'
9
+ templates = -> { Hash[ProvisioningTemplate.where(template_kind: TemplateKind.where(name: 'Bootdisk')).map { |temp| [temp[:name], temp[:name]] }] }
10
10
 
11
- Setting.transaction do
12
11
  [
13
- self.set('bootdisk_ipxe_dir', N_('Path to directory containing iPXE images'), ipxe, N_('iPXE directory')),
14
- self.set('bootdisk_isolinux_dir', N_('Path to directory containing isolinux images'), isolinux, N_('ISOLINUX directory')),
15
- self.set('bootdisk_syslinux_dir', N_('Path to directory containing syslinux images'), syslinux, N_('SYSLINUX directory')),
16
- self.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),
17
- self.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),
18
- self.set('bootdisk_mkiso_command', N_('Command to generate ISO image, use genisoimage or mkisofs'), 'genisoimage', N_('ISO generation command')),
19
- self.set('bootdisk_cache_media', N_('Installation media files will be cached for full host images'), true, N_('Installation media caching')),
20
- ].compact.each { |s| self.create s.update(:category => "Setting::Bootdisk") }
12
+ set('bootdisk_ipxe_dir', N_('Path to directory containing iPXE images'), ipxe, N_('iPXE directory')),
13
+ set('bootdisk_isolinux_dir', N_('Path to directory containing isolinux images'), isolinux, N_('ISOLINUX directory')),
14
+ set('bootdisk_syslinux_dir', N_('Path to directory containing syslinux images'), syslinux, N_('SYSLINUX directory')),
15
+ set('bootdisk_host_template', N_('iPXE template to use for host-specific boot disks'),
16
+ 'Boot disk iPXE - host', N_('Host image template'), nil, collection: templates),
17
+ set('bootdisk_generic_host_template', N_('iPXE template to use for generic host boot disks'),
18
+ 'Boot disk iPXE - generic host', N_('Generic image template'), nil, collection: templates),
19
+ set('bootdisk_mkiso_command', N_('Command to generate ISO image, use genisoimage or mkisofs'), 'genisoimage', N_('ISO generation command')),
20
+ set('bootdisk_cache_media', N_('Installation media files will be cached for full host images'), true, N_('Installation media caching'))
21
+ ]
21
22
  end
22
23
 
23
- true
24
-
25
- end
26
-
27
- def self.humanized_category
28
- N_('Boot disk')
24
+ def self.humanized_category
25
+ N_('Boot disk')
26
+ end
29
27
  end
30
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'net/http'
2
4
  require 'tempfile'
3
5
  require 'tmpdir'
@@ -6,137 +8,175 @@ require 'uri'
6
8
  # Generates an iPXE ISO hybrid image
7
9
  #
8
10
  # requires syslinux, ipxe/ipxe-bootimgs, genisoimage, isohybrid
9
- class ForemanBootdisk::ISOGenerator
10
- def self.generate_full_host(host, opts = {}, &block)
11
- raise ::Foreman::Exception.new(N_('Host is not in build mode, so the template cannot be rendered')) unless host.build?
12
-
13
- tmpl = host.send(:generate_pxe_template, :PXELinux)
14
- unless tmpl
15
- err = host.errors.full_messages.to_sentence
16
- raise ::Foreman::Exception.new(N_('Unable to generate disk template, PXELinux template not found or: %s'), err)
11
+ module ForemanBootdisk
12
+ class ISOGenerator
13
+ def self.generate_full_host(host, opts = {}, &block)
14
+ raise(Foreman::Exception, N_('Host is not in build mode, so the template cannot be rendered')) unless host.build?
15
+
16
+ tmpl = render_pxelinux_template(host)
17
+
18
+ # pxe_files and filename conversion is utterly bizarre
19
+ # aim to convert filenames to something usable under ISO 9660, to match as rendered in the template
20
+ # and then still ensure that the fetch() process stores them under the same name
21
+ files = host.operatingsystem.family.constantize::PXEFILES.keys.each_with_object({}) do |type, hash|
22
+ filename = host.operatingsystem.bootfile(host.medium_provider, type)
23
+ iso_filename = iso9660_filename(filename)
24
+ hash[iso_filename] = host.url_for_boot(type)
25
+ end
26
+
27
+ generate(opts.merge(isolinux: tmpl, files: files), &block)
17
28
  end
18
29
 
19
- # pxe_files and filename conversion is utterly bizarre
20
- # aim to convert filenames to something usable under ISO 9660, update the template to match
21
- # and then still ensure that the fetch() process stores them under the same name
22
- files = host.operatingsystem.pxe_files(host.medium, host.architecture, host)
23
- files.map! do |bootfile_info|
24
- bootfile_info.map do |f|
25
- suffix = f[1].split('/').last
26
- iso_f0 = iso9660_filename(f[0].to_s + '_' + suffix)
27
- tmpl.gsub!(f[0].to_s + '-' + suffix, iso_f0)
28
- ForemanBootdisk.logger.debug("Boot file #{iso_f0}, source #{f[1]}")
29
- [iso_f0, f[1]]
30
+ def self.render_pxelinux_template(host)
31
+ pxelinux_template = host.provisioning_template(kind: :PXELinux)
32
+
33
+ raise(Foreman::Exception, N_('Unable to generate disk template, PXELinux template not found.')) unless pxelinux_template
34
+
35
+ template = ForemanBootdisk::Renderer.new.render_template(
36
+ template: pxelinux_template,
37
+ host: host,
38
+ scope_class: ForemanBootdisk::Scope::FullHostBootdisk
39
+ )
40
+
41
+ unless template
42
+ err = host.errors.full_messages.to_sentence
43
+ raise(::Foreman::Exception.new(N_('Unable to generate disk PXELinux template: %s'), err))
30
44
  end
45
+
46
+ template
31
47
  end
32
48
 
33
- generate(opts.merge(:isolinux => tmpl, :files => files), &block)
34
- end
49
+ def self.generate(opts = {})
50
+ opts[:isolinux] = <<~ISOLINUX if opts[:isolinux].nil? && opts[:ipxe]
51
+ default ipxe
52
+ label ipxe
53
+ kernel /ipxe
54
+ initrd /script
55
+ ISOLINUX
35
56
 
36
- def self.generate(opts = {}, &block)
37
- opts[:isolinux] = <<-EOS if opts[:isolinux].nil? && opts[:ipxe]
38
- default ipxe
39
- label ipxe
40
- kernel /ipxe
41
- initrd /script
42
- EOS
57
+ Dir.mktmpdir('bootdisk') do |wd|
58
+ Dir.mkdir(File.join(wd, 'build'))
43
59
 
44
- Dir.mktmpdir('bootdisk') do |wd|
45
- Dir.mkdir(File.join(wd, 'build'))
60
+ if opts[:isolinux]
61
+ isolinux_source_file = File.join(Setting[:bootdisk_isolinux_dir], 'isolinux.bin')
62
+ raise(Foreman::Exception, N_('Please ensure the isolinux/syslinux package(s) are installed.')) unless File.exist?(isolinux_source_file)
46
63
 
47
- if opts[:isolinux]
48
- unless File.exists?(File.join(Setting[:bootdisk_isolinux_dir], 'isolinux.bin'))
49
- raise ::Foreman::Exception.new(N_("Please ensure the isolinux/syslinux package(s) are installed."))
50
- end
51
- FileUtils.cp(File.join(Setting[:bootdisk_isolinux_dir], 'isolinux.bin'), File.join(wd, 'build', 'isolinux.bin'))
52
- if File.exist?(File.join(Setting[:bootdisk_syslinux_dir], 'ldlinux.c32'))
53
- FileUtils.cp(File.join(Setting[:bootdisk_syslinux_dir], 'ldlinux.c32'), File.join(wd, 'build', 'ldlinux.c32'))
54
- end
55
- File.open(File.join(wd, 'build', 'isolinux.cfg'), 'w') do |file|
56
- file.write(opts[:isolinux])
64
+ FileUtils.cp(isolinux_source_file, File.join(wd, 'build', 'isolinux.bin'))
65
+
66
+ source_files = ['ldlinux.c32', 'menu.c32']
67
+ source_files.each do |source_file|
68
+ full_path = File.join(Setting[:bootdisk_syslinux_dir], source_file)
69
+ FileUtils.cp(full_path, File.join(wd, 'build', source_file)) if File.exist?(full_path)
70
+ end
71
+
72
+ File.open(File.join(wd, 'build', 'isolinux.cfg'), 'w') do |file|
73
+ file.write(opts[:isolinux])
74
+ end
57
75
  end
58
- end
59
76
 
60
- if opts[:ipxe]
61
- unless File.exists?(File.join(Setting[:bootdisk_ipxe_dir], 'ipxe.lkrn'))
62
- raise ::Foreman::Exception.new(N_("Please ensure the ipxe-bootimgs package is installed."))
77
+ if opts[:ipxe]
78
+ ipxe_source_file = File.join(Setting[:bootdisk_ipxe_dir], 'ipxe.lkrn')
79
+ raise(Foreman::Exception, N_('Please ensure the ipxe-bootimgs package is installed.')) unless File.exist?(ipxe_source_file)
80
+
81
+ FileUtils.cp(ipxe_source_file, File.join(wd, 'build', 'ipxe'))
82
+ File.open(File.join(wd, 'build', 'script'), 'w') { |file| file.write(opts[:ipxe]) }
63
83
  end
64
- FileUtils.cp(File.join(Setting[:bootdisk_ipxe_dir], 'ipxe.lkrn'), File.join(wd, 'build', 'ipxe'))
65
- File.open(File.join(wd, 'build', 'script'), 'w') { |file| file.write(opts[:ipxe]) }
66
- end
67
84
 
68
- if opts[:files]
69
- opts[:files].each do |bootfile_info|
70
- for file, source in bootfile_info do
71
- fetch(File.join(wd, 'build', file), source)
85
+ if opts[:files]
86
+ if opts[:files].respond_to?(:each)
87
+ opts[:files].each do |file, source|
88
+ fetch(File.join(wd, 'build', file), source)
89
+ end
72
90
  end
73
- end if opts[:files].respond_to? :each
74
- end
91
+ end
75
92
 
76
- iso = if opts[:dir]
77
- Tempfile.new(['bootdisk', '.iso'], opts[:dir]).path
78
- else
79
- File.join(wd, 'output.iso')
80
- end
81
- unless system("#{Setting[:bootdisk_mkiso_command]} -o #{iso} -iso-level 2 -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table #{File.join(wd, 'build')}")
82
- raise ::Foreman::Exception.new(N_("ISO build failed"))
83
- end
93
+ iso = if opts[:dir]
94
+ Tempfile.new(['bootdisk', '.iso'], opts[:dir]).path
95
+ else
96
+ File.join(wd, 'output.iso')
97
+ end
98
+ raise(Foreman::Exception, N_('ISO build failed')) unless system(build_mkiso_command(output_file: iso, source_directory: File.join(wd, 'build')))
99
+
100
+ # Make the ISO bootable as a HDD/USB disk too
101
+ raise(Foreman::Exception, N_('ISO hybrid conversion failed')) unless system('isohybrid', iso)
84
102
 
85
- # Make the ISO bootable as a HDD/USB disk too
86
- unless system("isohybrid", iso)
87
- raise ::Foreman::Exception.new(N_("ISO hybrid conversion failed"))
103
+ yield iso
88
104
  end
105
+ end
89
106
 
90
- yield iso
107
+ def self.build_mkiso_command(output_file:, source_directory:)
108
+ arguments = [
109
+ "-o #{output_file}",
110
+ '-iso-level 2',
111
+ '-b isolinux.bin',
112
+ '-c boot.cat',
113
+ '-no-emul-boot',
114
+ '-boot-load-size 4',
115
+ '-boot-info-table'
116
+ ]
117
+ [Setting[:bootdisk_mkiso_command], arguments, source_directory].flatten.join(' ')
91
118
  end
92
- end
93
119
 
94
- def self.token_expiry(host)
95
- expiry = host.token.try(:expires)
96
- return '' if Setting[:token_duration] == 0 || expiry.blank?
97
- '_' + expiry.strftime('%Y%m%d_%H%M')
98
- end
120
+ def self.token_expiry(host)
121
+ expiry = host.token.try(:expires)
122
+ return '' if Setting[:token_duration].zero? || expiry.blank?
123
+
124
+ '_' + expiry.strftime('%Y%m%d_%H%M')
125
+ end
99
126
 
100
- private
101
-
102
- def self.fetch(path, uri)
103
- dir = File.dirname(path)
104
- FileUtils.mkdir_p(dir) unless File.exist?(dir)
105
-
106
- use_cache = !!Setting[:bootdisk_cache_media]
107
- write_cache = false
108
- File.open(path, 'w') do |file|
109
- file.binmode
110
-
111
- if use_cache && !(contents = Rails.cache.fetch(uri, :raw => true)).nil?
112
- ForemanBootdisk.logger.info("Retrieved #{uri} from local cache (use foreman-rake tmp:cache:clear to empty)")
113
- file.write(contents)
114
- else
115
- ForemanBootdisk.logger.info("Fetching #{uri}")
116
- write_cache = use_cache
117
- uri = URI(uri)
118
- Net::HTTP.start(uri.host, uri.port) do |http|
119
- request = Net::HTTP::Get.new uri.request_uri
120
-
121
- http.request request do |response|
122
- response.read_body do |chunk|
123
- file.write chunk
127
+ def self.fetch(path, uri, limit = 10)
128
+ dir = File.dirname(path)
129
+ FileUtils.mkdir_p(dir) unless File.exist?(dir)
130
+
131
+ use_cache = !!Setting[:bootdisk_cache_media]
132
+ write_cache = false
133
+ File.open(path, 'w') do |file|
134
+ file.binmode
135
+
136
+ if use_cache && !(contents = Rails.cache.fetch(uri, raw: true)).nil?
137
+ ForemanBootdisk.logger.info("Retrieved #{uri} from local cache (use foreman-rake tmp:cache:clear to empty)")
138
+ file.write(contents)
139
+ else
140
+ ForemanBootdisk.logger.info("Fetching #{uri}")
141
+ write_cache = use_cache
142
+ uri = URI(uri)
143
+ Net::HTTP.start(uri.host, uri.port) do |http|
144
+ request = Net::HTTP::Get.new(uri.request_uri, 'Accept-Encoding' => 'plain')
145
+
146
+ http.request(request) do |response|
147
+ case response
148
+ when Net::HTTPSuccess then
149
+ response.read_body do |chunk|
150
+ file.write chunk
151
+ end
152
+ when Net::HTTPRedirection then
153
+ raise("Too many HTTP redirects when downloading #{uri}") if limit <= 0
154
+
155
+ fetch(path, response['location'], limit - 1)
156
+ # prevent multiple writes to the cache
157
+ write_cache = false
158
+ else
159
+ raise ::Foreman::Exception, N_(format("Unable to download boot file %{uri}, HTTP return code %{code}", uri: uri, code: response.code))
160
+ end
124
161
  end
125
162
  end
126
163
  end
127
164
  end
128
- end
129
165
 
130
- if write_cache
166
+ return unless write_cache
167
+
168
+ contents = File.read(path)
169
+ return if contents.empty?
170
+
131
171
  ForemanBootdisk.logger.debug("Caching contents of #{uri}")
132
- Rails.cache.write(uri, File.read(path), :raw => true)
172
+ Rails.cache.write(uri, contents, raw: true)
133
173
  end
134
- end
135
174
 
136
- # isolinux supports up to ISO 9660 level 2 filenames
137
- def self.iso9660_filename(name)
138
- dir = File.dirname(name)
139
- file = File.basename(name).upcase.tr_s('^A-Z0-9_', '_').last(28)
140
- dir == '.' ? file : File.join(dir.upcase.tr_s('^A-Z0-9_', '_').last(28), file)
175
+ # isolinux supports up to ISO 9660 level 2 filenames
176
+ def self.iso9660_filename(name)
177
+ dir = File.dirname(name)
178
+ file = File.basename(name).upcase.tr_s('^A-Z0-9_', '_').last(28)
179
+ dir == '.' ? file : File.join(dir.upcase.tr_s('^A-Z0-9_', '_').last(28), file)
180
+ end
141
181
  end
142
182
  end