foreman_bootdisk 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## v1.1.0
4
+ * per-host USB image support using isohybrid
5
+ * templates updated for multi-NIC support
6
+ * Ruby 1.8.7 fixes
7
+
8
+ ## v1.0.0
9
+ * initial release
10
+ * per-host ISO image support
data/README.md CHANGED
@@ -5,9 +5,9 @@ DHCP and TFTP services. However many users don't have these available, so
5
5
  foreman_bootdisk provides both a per-host and generic boot disks to enable
6
6
  deployments in datacentres without these capabilities.
7
7
 
8
- Boot images can be written as ISO images or for USB disks (TODO), and booted
9
- either from physical media or virtual disk/CDROM (via a lights out management
10
- device).
8
+ Boot images are written as hybrid ISO images (usable as ISOs or USB disks),
9
+ and booted either from physical media or virtual disk/CDROM (via a lights out
10
+ management device).
11
11
 
12
12
  # Installation
13
13
 
@@ -25,6 +25,7 @@ RPM users can install the "ruby193-rubygem-foreman_bootdisk" or
25
25
 
26
26
  * iPXE images are required
27
27
  * syslinux is required
28
+ * mkisofs and isohybrid are required
28
29
 
29
30
  gPXE images are unsupported due to lack of initrd support, but the name will
30
31
  crop up as Foreman's script support is still named after the project.
@@ -49,11 +50,10 @@ The templates used on the boot disks themselves are read-only so they can be
49
50
  updated in new versions of the plugin. To customise, copy the contents to a
50
51
  new template and set the name in More>Settings>Bootdisk.
51
52
 
52
- An OS gPXE provisioning template is required, e.g. "Kickstart default gPXE"
53
- (as supplied by Foreman). Ensure the OSes are ticked under the Associations
54
- tab and that the gPXE template is selected under the Templates tab on the OS.
55
-
56
- TODO: missing Debian template, kickstart gPXE template assumes `net0`
53
+ An OS gPXE provisioning template is required, preferably "Kickstart boot disk
54
+ gPXE" (as supplied by this plugin). Ensure the OSes are ticked under the
55
+ Associations tab and that the gPXE template is selected under the Templates tab
56
+ on the OS.
57
57
 
58
58
  Lastly, the OS provision template (i.e. kickstart/preseed) should provide the
59
59
  static IP details required to configure the OS. For a kickstart file, the
@@ -61,6 +61,14 @@ following configuration will do this:
61
61
 
62
62
  network --bootproto <%= @static ? "static" : "dhcp" %> --hostname <%= @host %> <%= "--ip=#{@host.ip} --netmask=#{@host.subnet.mask} --gateway=#{@host.subnet.gateway} --nameserver=#{@host.subnet.dns_primary},#{@host.subnet.dns_secondary}" if @static %>
63
63
 
64
+ ## USB images
65
+
66
+ The ISO images generated are run through `isohybrid` which makes them bootable
67
+ as disks too, suitable for copying to a USB device.
68
+
69
+ Use `dd if=fqdn.iso of=/dev/sdb` or similar to copy the image to a USB disk.
70
+ Ensure the device name is correct to avoid writing over the wrong disk.
71
+
64
72
  ## Per-host images
65
73
 
66
74
  Using the host and subnet data in Foreman, per-host images can be created with
@@ -68,15 +76,14 @@ fully static networking. The behaviour is dynamic, as the image chainloads
68
76
  from Foreman, so the current OS and build state will be provided by Foreman
69
77
  instead of being stored in the image.
70
78
 
71
- To generate the image from the web interface, view the host page, click the
72
- "Boot disk" button and select the image type from the menu.
79
+ To generate the image from the web interface, view the host page and click the
80
+ "Boot disk" button.
73
81
 
74
82
  To generate from the command line:
75
83
 
76
84
  foreman-rake bootdisk:generate:host NAME=foo.example.com
77
85
 
78
- Optionally set `TYPE=iso` or `TYPE=usb` to change the image type, or
79
- `OUTPUT=/path/foo.iso` to change the output destination.
86
+ Optionally set `OUTPUT=/path/foo.iso` to change the output destination.
80
87
 
81
88
  ## Generic host group images
82
89
 
@@ -88,8 +95,6 @@ Report issues on the Redmine project: [foreman_bootdisk](http://projects.thefore
88
95
 
89
96
  ## Known issues
90
97
 
91
- * USB support not implemented
92
- * Templates only support first NIC
93
98
  * No Debian guidance or templates
94
99
  * No SELinux policy support
95
100
 
@@ -8,10 +8,7 @@ module Bootdisk::HostsHelperExt
8
8
  def host_title_actions_with_bootdisk(host, vm)
9
9
  title_actions(
10
10
  button_group(
11
- select_action_button(_('Boot disk'),
12
- display_link_if_authorized(_("ISO image"), hash_for_bootdisk_iso_host_path(:id => @host), :class=>'btn'),
13
- display_link_if_authorized(_("USB image"), hash_for_bootdisk_iso_host_path(:id => @host), :class=>'btn'),
14
- )
11
+ display_link_if_authorized(_("Boot disk"), hash_for_bootdisk_iso_host_path(:id => @host), :class=>'btn')
15
12
  )
16
13
  )
17
14
  host_title_actions_without_bootdisk(host, vm)
@@ -3,18 +3,21 @@
3
3
  module Bootdisk::ConfigTemplateExt
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ BOOTDISK_TMPLS = ['Boot disk gPXE - host', 'Kickstart boot disk gPXE']
7
+
6
8
  included do
7
9
  before_destroy :bootdisk_destroy?
8
10
  validate :bootdisk_readonly
9
11
  end
10
12
 
11
13
  def bootdisk_destroy?
14
+ return true if ARGV.find { |a| a.start_with? "db:migrate" }
12
15
  bootdisk_readonly
13
16
  errors.empty?
14
17
  end
15
18
 
16
19
  def bootdisk_readonly
17
- if ['Boot disk gPXE - host'].include? name_was
20
+ if BOOTDISK_TMPLS.include? name_was
18
21
  errors.add(:base, _("Template is read-only as it's supplied in foreman_bootdisk. Please copy it to a new template to customize."))
19
22
  end
20
23
  end
@@ -1,6 +1,6 @@
1
- # Generates an iPXE ISO image
1
+ # Generates an iPXE ISO hybrid image
2
2
  #
3
- # requires syslinux, ipxe/ipxe-bootimgs, mkisofs
3
+ # requires syslinux, ipxe/ipxe-bootimgs, mkisofs, isohybrid
4
4
  class Bootdisk::ISOGenerator
5
5
  attr_reader :script
6
6
 
@@ -11,22 +11,29 @@ class Bootdisk::ISOGenerator
11
11
  def generate(&block)
12
12
  Dir.mktmpdir('bootdisk') do |wd|
13
13
  Dir.mkdir(File.join(wd, 'build'))
14
- File.write(File.join(wd, 'build', 'isolinux.cfg'), <<EOF)
14
+ File.open(File.join(wd, 'build', 'isolinux.cfg'),'w') do |file|
15
+ file.write(<<EOF)
15
16
  default ipxe
16
17
  label ipxe
17
18
  kernel /ipxe
18
19
  initrd /script
19
20
  EOF
21
+ end
20
22
 
21
23
  FileUtils.cp(File.join(Setting[:bootdisk_syslinux_dir], 'isolinux.bin'), File.join(wd, 'build', 'isolinux.bin'))
22
24
  FileUtils.cp(File.join(Setting[:bootdisk_ipxe_dir], 'ipxe.lkrn'), File.join(wd, 'build', 'ipxe'))
23
- File.write(File.join(wd, 'build', 'script'), script)
25
+ File.open(File.join(wd, 'build', 'script'),'w') { |file| file.write(script) }
24
26
 
25
27
  iso = File.join(wd, 'output.iso')
26
28
  unless system("mkisofs -o #{iso} -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table #{File.join(wd, 'build')}")
27
29
  raise ::Foreman::Exception.new(N_("ISO build failed"))
28
30
  end
29
31
 
32
+ # Make the ISO bootable as a HDD/USB disk too
33
+ unless system("isohybrid", iso)
34
+ raise ::Foreman::Exception.new(N_("ISO hybrid conversion failed"))
35
+ end
36
+
30
37
  yield iso
31
38
  end
32
39
  end
@@ -0,0 +1,21 @@
1
+ #!ipxe
2
+ # Example foreman_bootdisk host template
3
+ # This template is rendered for use inside a host-specific boot disk.
4
+ #
5
+ # Copy this template to customize it, the original is read-only.
6
+
7
+ # TODO: loop over net* until the host's MAC matches
8
+ ifopen net0
9
+ set net0/ip <%= @host.ip %>
10
+ set net0/netmask <%= @host.subnet.mask %>
11
+ set net0/gateway <%= @host.subnet.gateway %>
12
+ route
13
+
14
+ # Note, iPXE can only use one DNS server
15
+ set dns <%= @host.subnet.dns_primary %> <%= @host.subnet.dns_secondary %>
16
+ set net0/dns ${dns}
17
+ set domain <%= @host.domain.to_s %>
18
+
19
+ # Chainload from Foreman rather than embedding OS info here, so the behaviour
20
+ # is entirely dynamic.
21
+ chain <%= foreman_url("gPXE") %>
@@ -0,0 +1,38 @@
1
+ #!ipxe
2
+ # Example foreman_bootdisk host template
3
+ # This template is rendered for use inside a host-specific boot disk.
4
+ #
5
+ # Copy this template to customize it, the original is read-only.
6
+
7
+ # loop over net* until the host's MAC matches
8
+ <% (0..32).each do |i| -%>
9
+ :net<%= i %>
10
+ isset ${net<%= i -%>/mac} || goto no_nic
11
+ echo net<%= i -%> is a ${net<%= i -%>/chip} with MAC ${net<%= i -%>/mac}
12
+ iseq ${net<%= i -%>/mac} <%= @host.mac -%> || goto net<%= i+1 %>
13
+ ifopen net<%= i %>
14
+ set idx:int32 <%= i %>
15
+ goto loop_success
16
+ <% end -%>
17
+
18
+ :loop_success
19
+ echo Configuring net${idx} for static IP address
20
+ ifopen net${idx}
21
+ set netX/ip <%= @host.ip %>
22
+ set netX/netmask <%= @host.subnet.mask %>
23
+ set netX/gateway <%= @host.subnet.gateway %>
24
+ route
25
+
26
+ # Note, iPXE can only use one DNS server
27
+ set dns <%= @host.subnet.dns_primary %> <%= @host.subnet.dns_secondary %>
28
+ set domain <%= @host.domain.to_s %>
29
+
30
+ # Chainload from Foreman rather than embedding OS info here, so the behaviour
31
+ # is entirely dynamic.
32
+ chain <%= foreman_url("gPXE") %>
33
+ exit 0
34
+
35
+ :no_nic
36
+ echo Cannot find interface with MAC <%= @host.mac %>
37
+ sleep 30
38
+ exit 1
@@ -0,0 +1,5 @@
1
+ #!gpxe
2
+ kernel <%= "#{@host.url_for_boot(:kernel)}" %> ks=<%= foreman_url("provision")%>?static=yes ksdevice=<%= @host.mac %> network kssendmac ip=${netX/ip} netmask=${netX/netmask} gateway=${netX/gateway} dns=${dns}
3
+ initrd <%= "#{@host.url_for_boot(:initrd)}" %>
4
+
5
+ boot
@@ -3,29 +3,7 @@ class CreateHostBootdiskTemplate < ActiveRecord::Migration
3
3
  ConfigTemplate.find_or_create_by_name(
4
4
  :name => 'Boot disk gPXE - host',
5
5
  :template_kind_id => TemplateKind.find_by_name('gPXE').try(:id),
6
- :template => <<EOS
7
- #!ipxe
8
- # Example foreman_bootdisk host template
9
- # This template is rendered for use inside a host-specific boot disk.
10
- #
11
- # Copy this template to customize it, the original is read-only.
12
-
13
- # TODO: loop over net* until the host's MAC matches
14
- ifopen net0
15
- set net0/ip <%= @host.ip %>
16
- set net0/netmask <%= @host.subnet.mask %>
17
- set net0/gateway <%= @host.subnet.gateway %>
18
- route
19
-
20
- # Note, iPXE can only use one DNS server
21
- set dns <%= @host.subnet.dns_primary %> <%= @host.subnet.dns_secondary %>
22
- set net0/dns ${dns}
23
- set domain <%= @host.domain.to_s %>
24
-
25
- # Chainload from Foreman rather than embedding OS info here, so the behaviour
26
- # is entirely dynamic.
27
- chain <%= foreman_url("gPXE") %>
28
- EOS
6
+ :template => File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'host_v1.erb'))
29
7
  )
30
8
  end
31
9
 
@@ -0,0 +1,11 @@
1
+ class EditHostBootdiskTemplateMultinic < ActiveRecord::Migration
2
+ def self.up
3
+ ConfigTemplate.find_by_name('Boot disk gPXE - host').update_attribute(
4
+ :template, File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'host_v2.erb')))
5
+ end
6
+
7
+ def self.down
8
+ ConfigTemplate.find_by_name('Boot disk gPXE - host').update_attribute(
9
+ :template, File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'host_v1.erb')))
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class CreateKickstartBootdiskTemplate < ActiveRecord::Migration
2
+ def self.up
3
+ ConfigTemplate.find_or_create_by_name(
4
+ :name => 'Kickstart boot disk gPXE',
5
+ :template_kind_id => TemplateKind.find_by_name('gPXE').try(:id),
6
+ :template => File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'kickstart_v1.erb'))
7
+ )
8
+ end
9
+
10
+ def self.down
11
+ ConfigTemplate.destroy_all(:name => 'Kickstart boot disk gPXE')
12
+ end
13
+ end
@@ -1,6 +1,6 @@
1
1
  module Bootdisk
2
2
  ENGINE_NAME = 'bootdisk'
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
 
5
5
  require 'bootdisk/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
6
6
  end
@@ -1,15 +1,11 @@
1
1
  namespace :bootdisk do
2
2
  namespace :generate do
3
- desc 'Generate a static boot disk for a specific host. NAME=fqdn, TYPE=iso (default) or usb, OUTPUT path'
3
+ desc 'Generate a static boot disk for a specific host. NAME=fqdn, OUTPUT path'
4
4
  task :host => :environment do
5
5
  host = Host::Base.find_by_name(ENV['NAME']) || raise("cannot find host '#{ENV['NAME']}', specify NAME=fqdn")
6
6
  tmpl = host.bootdisk_template_render
7
7
 
8
- type = (ENV['TYPE'] || 'iso').downcase
9
- case type
10
- when 'usb'; Bootdisk::USBGenerator
11
- else; Bootdisk::ISOGenerator
12
- end.new(tmpl).generate do |image|
8
+ Bootdisk::ISOGenerator.new(tmpl).generate do |image|
13
9
  output = ENV['OUTPUT'] || "#{host.name}.#{type}"
14
10
  FileUtils.cp image, output
15
11
  puts "Wrote #{output}"
metadata CHANGED
@@ -1,24 +1,35 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: foreman_bootdisk
3
- version: !ruby/object:Gem::Version
4
- version: 1.0.0
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 0
10
+ version: 1.1.0
5
11
  platform: ruby
6
- authors:
12
+ authors:
7
13
  - Dominic Cleal
8
14
  autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
- date: 2013-08-29 00:00:00.000000000 Z
17
+
18
+ date: 2013-09-15 00:00:00 Z
12
19
  dependencies: []
13
- description: Plugin for Foreman that creates iPXE-based boot disks to provision hosts
14
- without the need for PXE infrastructure.
20
+
21
+ description: Plugin for Foreman that creates iPXE-based boot disks to provision hosts without the need for PXE infrastructure.
15
22
  email: dcleal@redhat.com
16
23
  executables: []
24
+
17
25
  extensions: []
18
- extra_rdoc_files:
26
+
27
+ extra_rdoc_files:
28
+ - CHANGES.md
19
29
  - LICENSE
20
30
  - README.md
21
- files:
31
+ files:
32
+ - CHANGES.md
22
33
  - LICENSE
23
34
  - README.md
24
35
  - app/controllers/concerns/bootdisk/hosts_controller_ext.rb
@@ -27,33 +38,48 @@ files:
27
38
  - app/models/concerns/bootdisk/host_ext.rb
28
39
  - app/models/setting/bootdisk.rb
29
40
  - app/services/bootdisk/iso_generator.rb
41
+ - app/views/bootdisk/host_v1.erb
42
+ - app/views/bootdisk/host_v2.erb
43
+ - app/views/bootdisk/kickstart_v1.erb
30
44
  - config/routes.rb
31
45
  - db/migrate/20130914211030_create_host_bootdisk_template.rb
46
+ - db/migrate/20130915104500_edit_host_bootdisk_template_multinic.rb
47
+ - db/migrate/20130915133321_create_kickstart_bootdisk_template.rb
32
48
  - lib/bootdisk/engine.rb
33
49
  - lib/foreman_bootdisk.rb
34
50
  - lib/tasks/bootdisk.rake
35
51
  homepage: http://github.com/theforeman/foreman_bootdisk
36
- licenses:
52
+ licenses:
37
53
  - GPL-3
38
- metadata: {}
39
54
  post_install_message:
40
55
  rdoc_options: []
41
- require_paths:
56
+
57
+ require_paths:
42
58
  - lib
43
- required_ruby_version: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- required_rubygems_version: !ruby/object:Gem::Requirement
49
- requirements:
50
- - - '>='
51
- - !ruby/object:Gem::Version
52
- version: '0'
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
53
77
  requirements: []
78
+
54
79
  rubyforge_project:
55
- rubygems_version: 2.0.6
80
+ rubygems_version: 1.8.25
56
81
  signing_key:
57
- specification_version: 4
82
+ specification_version: 3
58
83
  summary: Create boot disks to provision hosts with Foreman
59
84
  test_files: []
85
+
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: b3533e45d6b16fee4d6c491d48539d5363cf856e
4
- data.tar.gz: c60a73d067c98d1ad7fdcebe0b858513ac2c48f9
5
- SHA512:
6
- metadata.gz: ca8ceaa8d47f2ffe6ebae5c77debca1c02cd23d30cb6803c764691994a77ee4778da498c566605965ec5e4e01e394e75e7dec68b635f768988946b658c7a89dc
7
- data.tar.gz: 5e70814bcbdea0e5e10a3eee1c050a07c75e159bd101d3ab251307f25980dd175dcfdb772797c57241c46342fe9eff6a5ff31a672ded3fe2a5cf3eaf4aa0de49