foreman_bootdisk 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Changelog
2
2
 
3
- ## v1.1.0
3
+ ## v1.2.0
4
+ * add generic image, relying on DHCP and a MAC/IP search
5
+ * fix inability to associate provided templates with OSes
6
+
7
+ # v1.1.0
4
8
  * per-host USB image support using isohybrid
5
9
  * templates updated for multi-NIC support
6
10
  * Ruby 1.8.7 fixes
data/README.md CHANGED
@@ -39,6 +39,7 @@ Some configuration is set under More>Settings>Bootdisk in the Foreman UI.
39
39
  * `bootdisk_ipxe_dir` points to the directory containing ipxe.lkrn
40
40
  * `bootdisk_syslinux_dir` points to the directory containing syslinux images
41
41
  * `bootdisk_host_template` is the name of the per-host boot disk template
42
+ * `bootdisk_generic_host_template` is the name of the generic boot disk template
42
43
 
43
44
  For per-host images, ensure host IP addresses and subnets are populated, and
44
45
  the subnet's gateway, subnet mask and DNS resolver(s) are correctly configured
@@ -61,23 +62,45 @@ following configuration will do this:
61
62
 
62
63
  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
64
 
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
-
72
- ## Per-host images
65
+ ## Available images
66
+
67
+ The image types have trade-offs, but are all meant for environments without
68
+ total control over the network infrastructure - so no DHCP reservations or
69
+ TFTP settings are needed.
70
+
71
+ <table>
72
+ <tr>
73
+ <th>Type</th>
74
+ <th>Generic</th>
75
+ <th>DHCP required</th>
76
+ <th>DHCP reservation</th>
77
+ <th>Pre-register host</th>
78
+ </tr>
79
+ <tr>
80
+ <td>Per-host image</td>
81
+ <td>No</td>
82
+ <td>No</td>
83
+ <td>No</td>
84
+ <td>Yes</td>
85
+ </tr>
86
+ <tr>
87
+ <td>Generic image</td>
88
+ <td>Yes</td>
89
+ <td>Yes</td>
90
+ <td>No</td>
91
+ <td>Yes</td>
92
+ </tr>
93
+ </table>
94
+
95
+ ### Per-host images
73
96
 
74
97
  Using the host and subnet data in Foreman, per-host images can be created with
75
98
  fully static networking. The behaviour is dynamic, as the image chainloads
76
99
  from Foreman, so the current OS and build state will be provided by Foreman
77
100
  instead of being stored in the image.
78
101
 
79
- To generate the image from the web interface, view the host page and click the
80
- "Boot disk" button.
102
+ To generate the image from the web interface, view the host page, click the
103
+ "Boot disk" button and select "Host 'FQDN' image".
81
104
 
82
105
  To generate from the command line:
83
106
 
@@ -85,10 +108,38 @@ To generate from the command line:
85
108
 
86
109
  Optionally set `OUTPUT=/path/foo.iso` to change the output destination.
87
110
 
88
- ## Generic host group images
111
+ ### Generic image
112
+
113
+ This provides a single ISO that can be used by all hosts, but since IP details
114
+ can't be stored inside, it requires a DHCP pool on the network to bootstrap.
115
+ It will boot and contact Foreman for template of a registered host matching a
116
+ MAC address or the IP the host was assigned by DHCP.
117
+
118
+ The installation can continue on either the DHCP or static IP depending on how
119
+ the OS gPXE template is configured, and could configure the assigned IP
120
+ address statically for the installed system via the kickstart file.
121
+
122
+ To generate the image from the web interface, view a host page, click the
123
+ "Boot disk" button and select "Generic image".
124
+
125
+ To generate from the command line:
126
+
127
+ foreman-rake bootdisk:generate:generic
128
+
129
+ Optionally set `OUTPUT=/path/foo.iso` to change the output destination.
130
+
131
+ ### Host group images
89
132
 
90
133
  TODO
91
134
 
135
+ ### USB images
136
+
137
+ The ISO images generated are run through `isohybrid` which makes them bootable
138
+ as disks too, suitable for copying to a USB device.
139
+
140
+ Use `dd if=fqdn.iso of=/dev/sdb` or similar to copy the image to a USB disk.
141
+ Ensure the device name is correct to avoid writing over the wrong disk.
142
+
92
143
  # Issues
93
144
 
94
145
  Report issues on the Redmine project: [foreman_bootdisk](http://projects.theforeman.org/projects/bootdisk/issues/new)
@@ -0,0 +1,9 @@
1
+ module Bootdisk
2
+ class DisksController < ::ApplicationController
3
+ def generic_iso
4
+ Bootdisk::ISOGenerator.new(Bootdisk::Renderer.new.generic_template_render).generate do |iso|
5
+ send_data File.read(iso), :filename => "bootdisk_#{Setting[:foreman_url]}.iso"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module Bootdisk::UnattendedControllerExt
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ alias_method_chain :find_host_by_ip_or_mac, :param_mac
6
+ end
7
+
8
+ def find_host_by_ip_or_mac_with_param_mac
9
+ request.env['HTTP_X_RHN_PROVISIONING_MAC_0'] = "unknown #{params['mac']}" unless request.env.has_key?('HTTP_X_RHN_PROVISIONING_MAC_0')
10
+ find_host_by_ip_or_mac_without_param_mac
11
+ end
12
+ end
@@ -8,7 +8,10 @@ module Bootdisk::HostsHelperExt
8
8
  def host_title_actions_with_bootdisk(host, vm)
9
9
  title_actions(
10
10
  button_group(
11
- display_link_if_authorized(_("Boot disk"), hash_for_bootdisk_iso_host_path(:id => @host), :class=>'btn')
11
+ select_action_button(_('Boot disk'),
12
+ display_link_if_authorized(_("Host '%s' image") % @host.name.split('.')[0], hash_for_bootdisk_iso_host_path(:id => @host), :class=>'btn'),
13
+ display_link_if_authorized(_("Generic image"), hash_for_generic_iso_disks_path, :class=>'btn')
14
+ )
12
15
  )
13
16
  )
14
17
  host_title_actions_without_bootdisk(host, vm)
@@ -17,7 +17,19 @@ module Bootdisk::ConfigTemplateExt
17
17
  end
18
18
 
19
19
  def bootdisk_readonly
20
- if BOOTDISK_TMPLS.include? name_was
20
+ c = changes
21
+
22
+ # ignore CRLF changes
23
+ if c['template'] && (c['template'][0].nil? || c['template'][0].gsub("\n", "\r\n") == c['template'][1])
24
+ c.delete 'template'
25
+ end
26
+
27
+ # ignore nil to false changes
28
+ c.delete 'snippet' if c['snippet'] == [nil, false]
29
+
30
+ # allow the user to associate it, just not change the content
31
+ other_attrs = c.keys.find { |f| !['template_combinations', 'template_associations'].include? f }
32
+ if BOOTDISK_TMPLS.include?(name_was) && other_attrs
21
33
  errors.add(:base, _("Template is read-only as it's supplied in foreman_bootdisk. Please copy it to a new template to customize."))
22
34
  end
23
35
  end
@@ -11,6 +11,7 @@ class Setting::Bootdisk< ::Setting
11
11
  self.set('bootdisk_ipxe_dir', _('Path to directory containing iPXE images'), ipxe),
12
12
  self.set('bootdisk_syslinux_dir', _('Path to directory containing syslinux images'), syslinux),
13
13
  self.set('bootdisk_host_template', _('gPXE template to use for host-specific boot disks'), 'Boot disk gPXE - host'),
14
+ self.set('bootdisk_generic_host_template', _('gPXE template to use for generic host boot disks'), 'Boot disk gPXE - generic host'),
14
15
  ].compact.each { |s| self.create s.update(:category => "Setting::Bootdisk") }
15
16
  end
16
17
 
@@ -0,0 +1,12 @@
1
+ module Bootdisk
2
+ class Renderer
3
+ include ::Foreman::Renderer
4
+ include Rails.application.routes.url_helpers
5
+
6
+ def generic_template_render
7
+ tmpl = ConfigTemplate.find_by_name(Setting[:bootdisk_generic_host_template]) || raise(::Foreman::Exception.new(N_('Unable to find template specified by %s setting'), 'bootdisk_generic_host_template'))
8
+ @host = Struct.new(:token).new(nil)
9
+ unattended_render(tmpl.template)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ #!ipxe
2
+ # Example foreman_bootdisk generic host template
3
+ #
4
+ # This template is generic, but it will chainload to Foreman so expects the
5
+ # host to be registered already.
6
+ #
7
+ # It loops through all interfaces using DHCP, requesting a template from
8
+ # Foreman in the hope that one of the MACs or IPs matches.
9
+ #
10
+ # Copy this template to customize it, the original is read-only.
11
+
12
+ # loop over net* until we can get a template
13
+ <% (0..32).each do |i| -%>
14
+ :net<%= i %>
15
+ isset ${net<%= i -%>/mac} || goto no_nic
16
+ echo net<%= i -%> is a ${net<%= i -%>/chip} with MAC ${net<%= i -%>/mac}
17
+ dhcp net<%= i %> || goto net<%= i+1 %>
18
+ chain <%= (u = URI.parse(foreman_url("gPXE")); u.query = "#{u.query}&mac="; u.to_s) %>${net<%= i -%>/mac} || goto net<%= i+1 %>
19
+ exit 0
20
+ <% end -%>
21
+
22
+ :no_nic
23
+ echo Failed to chainload from any network interface
24
+ sleep 30
25
+ exit 1
data/config/routes.rb CHANGED
@@ -1,4 +1,8 @@
1
- Foreman::Application.routes.draw do
1
+ Rails.application.routes.draw do
2
+ resources :disks, :module => 'bootdisk', :only => :index do
3
+ get 'generic_iso', :on => :collection
4
+ end
5
+
2
6
  constraints(:id => /[^\/]+/) do
3
7
  resources :hosts do
4
8
  member do
@@ -3,6 +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
+ :snippet => false,
6
7
  :template => File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'host_v1.erb'))
7
8
  )
8
9
  end
@@ -3,6 +3,7 @@ class CreateKickstartBootdiskTemplate < ActiveRecord::Migration
3
3
  ConfigTemplate.find_or_create_by_name(
4
4
  :name => 'Kickstart boot disk gPXE',
5
5
  :template_kind_id => TemplateKind.find_by_name('gPXE').try(:id),
6
+ :snippet => false,
6
7
  :template => File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'kickstart_v1.erb'))
7
8
  )
8
9
  end
@@ -0,0 +1,14 @@
1
+ class CreateGenericHostBootdiskTemplate < ActiveRecord::Migration
2
+ def self.up
3
+ ConfigTemplate.find_or_create_by_name(
4
+ :name => 'Boot disk gPXE - generic host',
5
+ :template_kind_id => TemplateKind.find_by_name('gPXE').try(:id),
6
+ :snippet => false,
7
+ :template => File.read(File.join(Bootdisk::Engine.root, 'app', 'views', 'bootdisk', 'generic_host_v1.erb'))
8
+ )
9
+ end
10
+
11
+ def self.down
12
+ ConfigTemplate.destroy_all(:name => 'Boot disk gPXE - generic host')
13
+ end
14
+ end
@@ -2,6 +2,8 @@ require 'foreman_bootdisk'
2
2
 
3
3
  module Bootdisk
4
4
  class Engine < ::Rails::Engine
5
+ engine_name Bootdisk::ENGINE_NAME
6
+
5
7
  config.autoload_paths += Dir["#{config.root}/app/controllers/concerns"]
6
8
  config.autoload_paths += Dir["#{config.root}/app/helpers/concerns"]
7
9
  config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
@@ -19,6 +21,7 @@ module Bootdisk
19
21
  Host::Managed.send(:include, Bootdisk::HostExt)
20
22
  HostsController.send(:include, Bootdisk::HostsControllerExt)
21
23
  HostsHelper.send(:include, Bootdisk::HostsHelperExt)
24
+ UnattendedController.send(:include, Bootdisk::UnattendedControllerExt)
22
25
  end
23
26
  end
24
27
  end
@@ -0,0 +1,3 @@
1
+ module Bootdisk
2
+ VERSION = '1.2.0'
3
+ end
@@ -1,6 +1,7 @@
1
+ require 'bootdisk/version'
2
+
1
3
  module Bootdisk
2
4
  ENGINE_NAME = 'bootdisk'
3
- VERSION = '1.1.0'
4
5
 
5
6
  require 'bootdisk/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
6
7
  end
@@ -6,7 +6,18 @@ namespace :bootdisk do
6
6
  tmpl = host.bootdisk_template_render
7
7
 
8
8
  Bootdisk::ISOGenerator.new(tmpl).generate do |image|
9
- output = ENV['OUTPUT'] || "#{host.name}.#{type}"
9
+ output = ENV['OUTPUT'] || "#{host.name}.iso"
10
+ FileUtils.cp image, output
11
+ puts "Wrote #{output}"
12
+ end
13
+ end
14
+
15
+ desc 'Generate a generic boot disk. OUTPUT=path'
16
+ task :generic => :environment do
17
+ tmpl = Bootdisk::Renderer.new.generic_template_render
18
+
19
+ Bootdisk::ISOGenerator.new(tmpl).generate do |image|
20
+ output = ENV['OUTPUT'] || "bootdisk_#{Setting[:foreman_url]}.iso"
10
21
  FileUtils.cp image, output
11
22
  puts "Wrote #{output}"
12
23
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_bootdisk
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 1.1.0
10
+ version: 1.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dominic Cleal
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-09-15 00:00:00 Z
18
+ date: 2013-09-17 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: Plugin for Foreman that creates iPXE-based boot disks to provision hosts without the need for PXE infrastructure.
@@ -32,12 +32,16 @@ files:
32
32
  - CHANGES.md
33
33
  - LICENSE
34
34
  - README.md
35
+ - app/controllers/bootdisk/disks_controller.rb
35
36
  - app/controllers/concerns/bootdisk/hosts_controller_ext.rb
37
+ - app/controllers/concerns/bootdisk/unattended_controller_ext.rb
36
38
  - app/helpers/concerns/bootdisk/hosts_helper_ext.rb
37
39
  - app/models/concerns/bootdisk/config_template_ext.rb
38
40
  - app/models/concerns/bootdisk/host_ext.rb
39
41
  - app/models/setting/bootdisk.rb
40
42
  - app/services/bootdisk/iso_generator.rb
43
+ - app/services/bootdisk/renderer.rb
44
+ - app/views/bootdisk/generic_host_v1.erb
41
45
  - app/views/bootdisk/host_v1.erb
42
46
  - app/views/bootdisk/host_v2.erb
43
47
  - app/views/bootdisk/kickstart_v1.erb
@@ -45,7 +49,9 @@ files:
45
49
  - db/migrate/20130914211030_create_host_bootdisk_template.rb
46
50
  - db/migrate/20130915104500_edit_host_bootdisk_template_multinic.rb
47
51
  - db/migrate/20130915133321_create_kickstart_bootdisk_template.rb
52
+ - db/migrate/20130915201457_create_generic_host_bootdisk_template.rb
48
53
  - lib/bootdisk/engine.rb
54
+ - lib/bootdisk/version.rb
49
55
  - lib/foreman_bootdisk.rb
50
56
  - lib/tasks/bootdisk.rake
51
57
  homepage: http://github.com/theforeman/foreman_bootdisk