foreman_bootdisk 12.0.1 → 16.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHORS +26 -0
- data/CHANGES.md +9 -0
- data/README.md +19 -0
- data/app/controllers/foreman_bootdisk/api/v2/disks_controller.rb +11 -9
- data/app/controllers/foreman_bootdisk/api/v2/subnet_disks_controller.rb +37 -31
- data/app/controllers/foreman_bootdisk/disks_controller.rb +24 -19
- data/app/helpers/concerns/foreman_bootdisk/hosts_helper_ext.rb +86 -45
- data/app/lib/foreman_bootdisk/scope/bootdisk.rb +23 -0
- data/app/lib/foreman_bootdisk/scope/full_host_bootdisk.rb +15 -0
- data/app/models/concerns/foreman_bootdisk/compute_resources/vmware.rb +4 -2
- data/app/models/concerns/foreman_bootdisk/host_ext.rb +33 -22
- data/app/models/concerns/foreman_bootdisk/orchestration/compute.rb +14 -10
- data/app/models/setting/bootdisk.rb +21 -23
- data/app/services/foreman_bootdisk/iso_generator.rb +144 -104
- data/app/services/foreman_bootdisk/renderer.rb +40 -21
- data/app/views/foreman_bootdisk/generic_host.erb +21 -3
- data/app/views/foreman_bootdisk/generic_static_host.erb +34 -0
- data/app/views/foreman_bootdisk/host.erb +29 -14
- data/config/routes.rb +15 -13
- data/config/routes/mount_engine.rb +3 -1
- data/db/migrate/20130914211030_create_host_bootdisk_template.rb +4 -4
- data/db/migrate/20130915104500_edit_host_bootdisk_template_multinic.rb +4 -4
- data/db/migrate/20130915133321_create_kickstart_bootdisk_template.rb +4 -4
- data/db/migrate/20130915201457_create_generic_host_bootdisk_template.rb +4 -4
- data/db/migrate/20131021095100_edit_host_bootdisk_template_dns_secondary.rb +4 -4
- data/db/migrate/20140522185700_change_templatekind_to_bootdisk.rb +16 -14
- data/db/migrate/20171009225200_remove_duplicate_bootdisk_templates.rb +4 -2
- data/db/seeds.d/50-bootdisk_templates.rb +21 -36
- data/lib/foreman_bootdisk.rb +2 -0
- data/lib/foreman_bootdisk/engine.rb +25 -37
- data/lib/foreman_bootdisk/version.rb +3 -1
- data/lib/tasks/bootdisk.rake +34 -17
- data/locale/ca/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ca/foreman_bootdisk.po +31 -15
- data/locale/de/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/de/foreman_bootdisk.po +40 -22
- data/locale/en/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/en/foreman_bootdisk.po +24 -9
- data/locale/en_GB/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/en_GB/foreman_bootdisk.po +31 -16
- data/locale/es/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/es/foreman_bootdisk.po +46 -31
- data/locale/foreman_bootdisk.pot +82 -54
- data/locale/fr/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/fr/foreman_bootdisk.po +30 -15
- data/locale/gemspec.rb +3 -1
- data/locale/it/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/it/foreman_bootdisk.po +27 -12
- data/locale/ja/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ja/foreman_bootdisk.po +30 -15
- data/locale/ko/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ko/foreman_bootdisk.po +27 -12
- data/locale/pt_BR/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/pt_BR/foreman_bootdisk.po +43 -27
- data/locale/ru/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/ru/foreman_bootdisk.po +28 -13
- data/locale/sv_SE/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/sv_SE/foreman_bootdisk.po +26 -11
- data/locale/zh_CN/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/zh_CN/foreman_bootdisk.po +46 -31
- data/locale/zh_TW/LC_MESSAGES/foreman_bootdisk.mo +0 -0
- data/locale/zh_TW/foreman_bootdisk.po +27 -12
- data/release-gem +84 -0
- data/test/functional/foreman_bootdisk/api/v2/disks_controller_test.rb +35 -33
- data/test/functional/foreman_bootdisk/api/v2/subnet_disks_controller_test.rb +9 -7
- data/test/functional/foreman_bootdisk/disks_controller_test.rb +27 -25
- data/test/models/host/managed_test.rb +26 -0
- data/test/test_plugin_helper.rb +11 -7
- data/test/unit/access_permissions_test.rb +2 -0
- data/test/unit/concerns/compute_resources/vmware_test.rb +67 -63
- data/test/unit/concerns/host_test.rb +54 -46
- data/test/unit/concerns/orchestration/compute_test.rb +41 -39
- data/test/unit/foreman_bootdisk/renderer_test.rb +36 -0
- data/test/unit/foreman_bootdisk/scope/bootdisk_test.rb +31 -0
- data/test/unit/foreman_bootdisk/scope/full_host_bootdisk_test.rb +30 -0
- data/test/unit/iso_generator_test.rb +67 -40
- metadata +69 -5
- data/app/services/foreman_bootdisk/renderer_methods.rb +0 -27
@@ -1,29 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
|
3
5
|
module ForemanBootdisk
|
4
6
|
class Renderer
|
5
|
-
include ::Foreman::Renderer
|
6
|
-
include Rails.application.routes.url_helpers
|
7
|
-
delegate :logger, :to => :ForemanBootdisk
|
8
|
-
include RendererMethods
|
9
|
-
|
10
7
|
def generic_template_render(subnet = nil)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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, :content_source).new(
|
12
|
+
nil,
|
13
|
+
Struct.new(:subnet).new(subnet),
|
14
|
+
nil
|
15
|
+
)
|
16
|
+
else
|
17
|
+
Struct.new(:token, :subnet, :content_source).new(nil, nil, nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
render_template(template: generic_host_template, host: host)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_template(template:, host:, scope_class: renderer_scope)
|
24
|
+
source = Foreman::Renderer.get_source(
|
25
|
+
template: template,
|
26
|
+
host: host
|
27
|
+
)
|
28
|
+
scope = Foreman::Renderer.get_scope(
|
29
|
+
host: host,
|
30
|
+
klass: scope_class
|
31
|
+
)
|
32
|
+
Foreman::Renderer.render(source, scope)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def renderer_scope
|
38
|
+
ForemanBootdisk::Scope::Bootdisk
|
39
|
+
end
|
40
|
+
|
41
|
+
def generic_host_template
|
42
|
+
template = ProvisioningTemplate.unscoped.find_by(name: Setting[:bootdisk_generic_host_template])
|
43
|
+
raise ::Foreman::Exception.new(N_('Unable to find template specified by %s setting'), 'bootdisk_generic_host_template') unless template
|
44
|
+
|
45
|
+
template
|
27
46
|
end
|
28
47
|
end
|
29
48
|
end
|
@@ -21,8 +21,26 @@ dhcp net<%= i %> || goto net<%= i+1 %>
|
|
21
21
|
chain <%= url %>${net<%= i -%>/mac} || goto net<%= i+1 %>
|
22
22
|
exit 0
|
23
23
|
<% end -%>
|
24
|
+
echo Failed to chainload from any network interface, fallback to static.
|
25
|
+
ifstat
|
24
26
|
|
25
27
|
:no_nic
|
26
|
-
echo
|
27
|
-
|
28
|
-
|
28
|
+
echo -n Enter interface name to boot from (e.g. net0): && read interface
|
29
|
+
isset ${${interface}/mac} && goto get_static_ip
|
30
|
+
echo Interface ${interface} is not initialized, try again
|
31
|
+
goto no_nic
|
32
|
+
|
33
|
+
:get_static_ip
|
34
|
+
ifopen ${interface}
|
35
|
+
echo Please enter IP details for ${interface}
|
36
|
+
echo
|
37
|
+
echo -n IP address : && read ${interface}/ip
|
38
|
+
echo -n Subnet mask : && read ${interface}/netmask
|
39
|
+
echo -n Default gateway : && read ${interface}/gateway
|
40
|
+
echo -n DNS server : && read dns
|
41
|
+
chain <%= url %>${${interface}/mac} || goto boot_failure
|
42
|
+
exit 0
|
43
|
+
|
44
|
+
:boot_failure
|
45
|
+
echo Cannot continue, spawning shell
|
46
|
+
shell
|
@@ -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
|
@@ -7,9 +7,23 @@
|
|
7
7
|
<%
|
8
8
|
interface = @host.provision_interface
|
9
9
|
bootdisk_raise(N_('Host has no provisioning interface defined')) unless interface
|
10
|
-
bootdisk_raise(N_('Host has no
|
11
|
-
bootdisk_raise(N_('Host has no subnet defined')) unless interface.subnet
|
10
|
+
bootdisk_raise(N_('Host has no IPv4 or IPv6 address defined')) unless interface.ip.present? || interface.ip6.present?
|
11
|
+
bootdisk_raise(N_('Host has no subnet defined')) unless interface.subnet || interface.subnet6
|
12
12
|
bootdisk_raise(N_('Host has no domain defined')) unless interface.domain
|
13
|
+
if interface.ip.present? && interface.subnet
|
14
|
+
ip = interface.ip
|
15
|
+
subnet = interface.subnet
|
16
|
+
elsif interface.ip6.present? && interface.subnet6
|
17
|
+
ip = interface.ip6
|
18
|
+
subnet = interface.subnet6
|
19
|
+
bootdisk_raise(N_('Host bootdisk does not work with static IPv6'))
|
20
|
+
else
|
21
|
+
bootdisk_raise(N_('Both IP and Subnet must be set'))
|
22
|
+
end
|
23
|
+
|
24
|
+
mask = subnet.mask
|
25
|
+
gw = subnet.gateway
|
26
|
+
dns = subnet.dns_servers.first
|
13
27
|
%>
|
14
28
|
|
15
29
|
echo Foreman Bootdisk: Host image (<%= @host.name %>)
|
@@ -25,20 +39,22 @@ goto loop_success
|
|
25
39
|
<% end -%>
|
26
40
|
|
27
41
|
:loop_success
|
28
|
-
echo Configuring net${idx} for static IP address <%=
|
42
|
+
echo Configuring net${idx} for static IP address <%= ip %>
|
29
43
|
ifopen net${idx}
|
30
|
-
|
31
|
-
set netX/
|
32
|
-
|
33
|
-
|
44
|
+
# netX = last opened NIC
|
45
|
+
set netX/ip <%= ip %>
|
46
|
+
set netX/netmask <%= mask %>
|
47
|
+
<% if gw.present? %>
|
48
|
+
set netX/gateway <%= gw %>
|
34
49
|
<% end %>
|
35
50
|
ifstat net${idx}
|
36
51
|
route
|
37
52
|
|
38
|
-
|
39
|
-
#
|
40
|
-
|
41
|
-
|
53
|
+
# Note: When multiple DNS servers are specified, only the first
|
54
|
+
# server will be used. See: http://ipxe.org/cfg/dns
|
55
|
+
<% if dns.present? -%>
|
56
|
+
echo Using DNS <%= dns %>
|
57
|
+
set dns <%= dns %>
|
42
58
|
set domain <%= interface.domain.to_s %>
|
43
59
|
<% end %>
|
44
60
|
|
@@ -48,6 +64,5 @@ chain <%= bootdisk_chain_url %>
|
|
48
64
|
exit 0
|
49
65
|
|
50
66
|
:no_nic
|
51
|
-
echo Cannot find interface with MAC <%= interface.mac
|
52
|
-
|
53
|
-
exit 1
|
67
|
+
echo Cannot find interface with MAC <%= interface.mac %>, spawning shell
|
68
|
+
shell
|
data/config/routes.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
ForemanBootdisk::Engine.routes.draw do
|
2
|
-
resources :disks, :
|
3
|
-
get 'generic', :
|
4
|
-
get 'help', :
|
5
|
-
constraints(:
|
6
|
-
get 'hosts/:id', :
|
7
|
-
get 'full_hosts/:id', :
|
8
|
-
get 'subnet/:id', :
|
4
|
+
resources :disks, only: [] do
|
5
|
+
get 'generic', on: :collection
|
6
|
+
get 'help', on: :collection
|
7
|
+
constraints(id: %r{[^/]+}) do
|
8
|
+
get 'hosts/:id', on: :collection, to: 'disks#host'
|
9
|
+
get 'full_hosts/:id', on: :collection, to: 'disks#full_host'
|
10
|
+
get 'subnet/:id', on: :collection, to: 'disks#subnet'
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
namespace :api, :
|
13
|
-
scope
|
14
|
-
get 'generic', :
|
15
|
-
constraints(:
|
16
|
-
get 'hosts/:id', :
|
17
|
-
get 'subnets/:id', :
|
14
|
+
namespace :api, defaults: { format: 'json' } do
|
15
|
+
scope '(:apiv)', module: :v2, defaults: { apiv: 'v2' }, apiv: /v1|v2/, constraints: ApiConstraints.new(version: 2, default: true) do
|
16
|
+
get 'generic', to: 'disks#generic'
|
17
|
+
constraints(id: %r{[^/]+}) do
|
18
|
+
get 'hosts/:id', to: 'disks#host'
|
19
|
+
get 'subnets/:id', to: 'subnet_disks#subnet'
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -1,29 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class ChangeTemplatekindToBootdisk < ActiveRecord::Migration[4.2]
|
2
4
|
class FakeConfigTemplate < ApplicationRecord
|
3
|
-
if ActiveRecord::
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
self.table_name = if ActiveRecord::Base.connection.migration_context.get_all_versions.include?(20_150_514_072_626)
|
6
|
+
'templates'
|
7
|
+
else
|
8
|
+
'config_templates'
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
def self.up
|
11
|
-
kind = TemplateKind.where(:
|
13
|
+
kind = TemplateKind.where(name: 'Bootdisk').first_or_create
|
12
14
|
|
13
|
-
tmpl_h = Setting.
|
14
|
-
tmpl_g = Setting.
|
15
|
+
tmpl_h = Setting.find_by(name: 'bootdisk_host_template').try(:value)
|
16
|
+
tmpl_g = Setting.find_by(name: 'bootdisk_generic_host_template').try(:value)
|
15
17
|
|
16
18
|
(FakeConfigTemplate.unscoped.where('name LIKE ?', '%Boot disk%') |
|
17
|
-
FakeConfigTemplate.unscoped.where(:
|
19
|
+
FakeConfigTemplate.unscoped.where(name: [tmpl_h, tmpl_g].compact)).each do |tmpl|
|
18
20
|
tmpl.update_attribute(:template_kind_id, kind.id)
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
24
|
def self.down
|
23
|
-
old_kind = TemplateKind.
|
24
|
-
new_kind = TemplateKind.
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
old_kind = TemplateKind.find_by(name: 'Bootdisk')
|
26
|
+
new_kind = TemplateKind.find_by(name: 'iPXE')
|
27
|
+
return unless old_kind.present? && new_kind.present?
|
28
|
+
|
29
|
+
FakeConfigTemplate.unscoped.where(template_kind_id: old_kind.id).update_all(template_kind_id: new_kind.id)
|
28
30
|
end
|
29
31
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class RemoveDuplicateBootdiskTemplates < ActiveRecord::Migration[4.2]
|
2
4
|
def up
|
3
5
|
template_names = ['Boot disk iPXE - host', 'Boot disk iPXE - generic host']
|
4
6
|
template_names.each do |template_name|
|
5
|
-
duplicate_template_ids = ProvisioningTemplate.unscoped.where(:
|
6
|
-
ProvisioningTemplate.unscoped.where(:
|
7
|
+
duplicate_template_ids = ProvisioningTemplate.unscoped.where(name: template_name, locked: true).order(created_at: :asc).pluck(:id).drop(1)
|
8
|
+
ProvisioningTemplate.unscoped.where(id: duplicate_template_ids).destroy_all if duplicate_template_ids.any?
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,46 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
ProvisioningTemplate.without_auditing do
|
8
|
-
content = File.read(File.join(ForemanBootdisk::Engine.root, 'app', 'views', 'foreman_bootdisk', 'host.erb'))
|
9
|
-
created << 'Boot disk iPXE - host' unless ProvisioningTemplate.find_by_name('Boot disk iPXE - host')
|
10
|
-
tmpl = ProvisioningTemplate.unscoped.where(:name => 'Boot disk iPXE - host').first_or_create do |template|
|
11
|
-
template.attributes = {
|
12
|
-
:template_kind_id => kind.id,
|
13
|
-
:snippet => false,
|
14
|
-
:template => content
|
15
|
-
}
|
16
|
-
end
|
17
|
-
tmpl.attributes = {
|
18
|
-
:template => content,
|
19
|
-
:default => true,
|
20
|
-
:vendor => "Foreman boot disk",
|
21
|
-
}
|
22
|
-
tmpl.locked = true
|
23
|
-
tmpl.save!(:validate => false) if tmpl.changes.present?
|
3
|
+
def read_bootdisk_template(filename)
|
4
|
+
File.read(File.join(ForemanBootdisk::Engine.root, 'app', 'views', 'foreman_bootdisk', filename))
|
5
|
+
end
|
24
6
|
|
25
|
-
|
26
|
-
|
27
|
-
tmpl = ProvisioningTemplate.unscoped.where(:name
|
7
|
+
def ensure_bootdisk_template(name, content)
|
8
|
+
kind = TemplateKind.unscoped.where(name: 'Bootdisk').first_or_create
|
9
|
+
tmpl = ProvisioningTemplate.unscoped.where(name: name).first_or_create do |template|
|
28
10
|
template.attributes = {
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
11
|
+
template_kind_id: kind.id,
|
12
|
+
snippet: false,
|
13
|
+
template: content
|
32
14
|
}
|
33
15
|
end
|
34
16
|
tmpl.attributes = {
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
17
|
+
template: content,
|
18
|
+
default: true,
|
19
|
+
vendor: "Foreman boot disk"
|
38
20
|
}
|
39
21
|
tmpl.locked = true
|
40
|
-
tmpl.
|
22
|
+
tmpl.organizations = Organization.unscoped.all if SETTINGS[:organizations_enabled]
|
23
|
+
tmpl.locations = Location.unscoped.all if SETTINGS[:locations_enabled]
|
24
|
+
tmpl.save!(validate: false) if tmpl.changes.present?
|
25
|
+
end
|
41
26
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
ProvisioningTemplate.without_auditing do
|
28
|
+
ensure_bootdisk_template("Boot disk iPXE - host", read_bootdisk_template("host.erb"))
|
29
|
+
ensure_bootdisk_template("Boot disk iPXE - generic host", read_bootdisk_template("generic_host.erb"))
|
30
|
+
ensure_bootdisk_template("Boot disk iPXE - generic static host", read_bootdisk_template("generic_static_host.erb"))
|
46
31
|
end
|