foreman_bootdisk 1.0.0 → 1.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.
- data/CHANGES.md +10 -0
- data/README.md +19 -14
- data/app/helpers/concerns/bootdisk/hosts_helper_ext.rb +1 -4
- data/app/models/concerns/bootdisk/config_template_ext.rb +4 -1
- data/app/services/bootdisk/iso_generator.rb +11 -4
- data/app/views/bootdisk/host_v1.erb +21 -0
- data/app/views/bootdisk/host_v2.erb +38 -0
- data/app/views/bootdisk/kickstart_v1.erb +5 -0
- data/db/migrate/20130914211030_create_host_bootdisk_template.rb +1 -23
- data/db/migrate/20130915104500_edit_host_bootdisk_template_multinic.rb +11 -0
- data/db/migrate/20130915133321_create_kickstart_bootdisk_template.rb +13 -0
- data/lib/foreman_bootdisk.rb +1 -1
- data/lib/tasks/bootdisk.rake +2 -6
- metadata +50 -24
- checksums.yaml +0 -7
data/CHANGES.md
ADDED
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
|
9
|
-
either from physical media or virtual disk/CDROM (via a lights out
|
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,
|
53
|
-
(as supplied by
|
54
|
-
tab and that the gPXE template is selected under the Templates tab
|
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
|
72
|
-
"Boot disk" button
|
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 `
|
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
|
-
|
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
|
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.
|
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.
|
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 =>
|
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
|
data/lib/foreman_bootdisk.rb
CHANGED
data/lib/tasks/bootdisk.rake
CHANGED
@@ -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,
|
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
|
-
|
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
|
-
|
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
|
-
|
17
|
+
|
18
|
+
date: 2013-09-15 00:00:00 Z
|
12
19
|
dependencies: []
|
13
|
-
|
14
|
-
|
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
|
-
|
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
|
-
|
56
|
+
|
57
|
+
require_paths:
|
42
58
|
- lib
|
43
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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:
|
80
|
+
rubygems_version: 1.8.25
|
56
81
|
signing_key:
|
57
|
-
specification_version:
|
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
|