boxgrinder-build 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +14 -0
- data/README.md +136 -0
- data/Rakefile +11 -6
- data/bin/boxgrinder-build +199 -0
- data/boxgrinder-build.gemspec +26 -14
- data/lib/boxgrinder-build/appliance.rb +6 -6
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +5 -3
- data/lib/boxgrinder-build/helpers/image-helper.rb +6 -0
- data/lib/boxgrinder-build/helpers/plugin-helper.rb +15 -4
- data/lib/boxgrinder-build/plugins/base-plugin.rb +1 -0
- data/lib/boxgrinder-build/plugins/delivery/ebs/ebs-plugin.rb +280 -0
- data/lib/boxgrinder-build/plugins/delivery/local/local-plugin.rb +66 -0
- data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +242 -0
- data/lib/boxgrinder-build/plugins/delivery/s3/src/cert-ec2.pem +23 -0
- data/lib/boxgrinder-build/plugins/delivery/sftp/sftp-plugin.rb +152 -0
- data/lib/boxgrinder-build/plugins/delivery/usb/usb-plugin.rb +43 -0
- data/lib/boxgrinder-build/plugins/os/centos/centos-plugin.rb +46 -0
- data/lib/boxgrinder-build/plugins/os/fedora/fedora-plugin.rb +61 -0
- data/lib/boxgrinder-build/plugins/os/rhel/rhel-plugin.rb +67 -0
- data/lib/boxgrinder-build/plugins/os/rpm-based/kickstart.rb +118 -0
- data/lib/boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin.rb +202 -0
- data/lib/boxgrinder-build/plugins/os/rpm-based/rpm-dependency-validator.rb +153 -0
- data/lib/boxgrinder-build/plugins/os/rpm-based/src/appliance.ks.erb +37 -0
- data/lib/boxgrinder-build/plugins/os/rpm-based/src/base.repo +4 -0
- data/lib/boxgrinder-build/plugins/os/rpm-based/src/motd.init +21 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/ec2-plugin.rb +239 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/src/fstab_32bit +7 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/src/fstab_64bit +7 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/src/ifcfg-eth0 +7 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/src/menu.lst +6 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/src/rc_local +19 -0
- data/lib/boxgrinder-build/plugins/platform/virtualbox/virtualbox-plugin.rb +62 -0
- data/lib/boxgrinder-build/plugins/platform/vmware/src/README-enterprise +18 -0
- data/lib/boxgrinder-build/plugins/platform/vmware/src/README-personal +16 -0
- data/lib/boxgrinder-build/plugins/platform/vmware/src/base.vmdk +20 -0
- data/lib/boxgrinder-build/plugins/platform/vmware/src/base.vmx +45 -0
- data/lib/boxgrinder-build/plugins/platform/vmware/vmware-plugin.rb +194 -0
- data/rubygem-boxgrinder-build.spec +73 -10
- data/spec/appliance-spec.rb +2 -2
- data/spec/helpers/guestfs-helper-spec.rb +4 -2
- data/spec/helpers/image-helper-spec.rb +4 -0
- data/spec/helpers/plugin-helper-spec.rb +0 -38
- data/spec/managers/plugin-manager-spec.rb +6 -6
- data/spec/plugins/delivery/ebs/ebs-plugin-spec.rb +230 -0
- data/spec/plugins/delivery/ebs/ebs.yaml +3 -0
- data/spec/plugins/delivery/local/local-plugin-spec.rb +133 -0
- data/spec/plugins/delivery/s3/s3-plugin-spec.rb +351 -0
- data/spec/plugins/delivery/sftp/sftp-plugin-spec.rb +26 -0
- data/spec/plugins/os/centos/centos-plugin-spec.rb +52 -0
- data/spec/plugins/os/fedora/fedora-plugin-spec.rb +73 -0
- data/spec/plugins/os/rhel/rhel-plugin-spec.rb +158 -0
- data/spec/plugins/os/rpm-based/kickstart-spec.rb +129 -0
- data/spec/plugins/os/rpm-based/rpm-based-os-plugin-spec.rb +162 -0
- data/spec/plugins/os/rpm-based/rpm-dependency-validator-spec.rb +50 -0
- data/spec/plugins/os/rpm-based/src/jeos-f13-plain.ks +20 -0
- data/spec/plugins/os/rpm-based/src/jeos-f13-without-version.ks +22 -0
- data/spec/plugins/os/rpm-based/src/jeos-f13.ks +23 -0
- data/spec/plugins/platform/ec2/ec2-plugin-spec.rb +339 -0
- data/spec/plugins/platform/virtualbox/virtualbox-plugin-spec.rb +118 -0
- data/spec/plugins/platform/vmware/vmware-plugin-spec.rb +299 -0
- metadata +149 -25
- data/README +0 -7
- data/bin/boxgrinder +0 -128
- data/lib/boxgrinder-build/helpers/thor-helper.rb +0 -85
@@ -0,0 +1,152 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'net/ssh'
|
21
|
+
require 'net/sftp'
|
22
|
+
require 'progressbar'
|
23
|
+
require 'boxgrinder-build/plugins/base-plugin'
|
24
|
+
require 'boxgrinder-build/helpers/package-helper'
|
25
|
+
|
26
|
+
module BoxGrinder
|
27
|
+
class SFTPPlugin < BasePlugin
|
28
|
+
def after_init
|
29
|
+
set_default_config_value('overwrite', false)
|
30
|
+
set_default_config_value('default_permissions', 0644)
|
31
|
+
|
32
|
+
register_deliverable(:package => "#{@appliance_config.name}-#{@appliance_config.version}.#{@appliance_config.release}-#{@appliance_config.os.name}-#{@appliance_config.os.version}-#{@appliance_config.hardware.arch}-#{current_platform}.tgz")
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute( type = :sftp )
|
36
|
+
validate_plugin_config(['path', 'username', 'host'], 'http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#SFTP_Delivery_Plugin')
|
37
|
+
|
38
|
+
PackageHelper.new(@config, @appliance_config, :log => @log, :exec_helper => @exec_helper).package( File.dirname(@previous_deliverables[:disk]), @deliverables[:package] )
|
39
|
+
|
40
|
+
@log.info "Uploading #{@appliance_config.name} appliance via SSH..."
|
41
|
+
|
42
|
+
begin
|
43
|
+
#TODO move to a block
|
44
|
+
connect
|
45
|
+
upload_files(@plugin_config['path'], File.basename(@deliverables[:package]) => @deliverables[:package])
|
46
|
+
disconnect
|
47
|
+
|
48
|
+
@log.info "Appliance #{@appliance_config.name} uploaded."
|
49
|
+
rescue => e
|
50
|
+
@log.error e
|
51
|
+
@log.error "An error occurred while uploading files."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def connect
|
56
|
+
@log.info "Connecting to #{@plugin_config['host']}..."
|
57
|
+
@ssh = Net::SSH.start(@plugin_config['host'], @plugin_config['username'], {:password => @plugin_config['password']})
|
58
|
+
end
|
59
|
+
|
60
|
+
def connected?
|
61
|
+
return true if !@ssh.nil? and !@ssh.closed?
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
def disconnect
|
66
|
+
@log.info "Disconnecting from #{@plugin_config['host']}..."
|
67
|
+
@ssh.close if connected?
|
68
|
+
@ssh = nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def upload_files(path, files = {})
|
72
|
+
return if files.size == 0
|
73
|
+
|
74
|
+
raise "You're not connected to server" unless connected?
|
75
|
+
|
76
|
+
@log.debug "Files to upload:"
|
77
|
+
|
78
|
+
files.each do |remote, local|
|
79
|
+
@log.debug "#{File.basename(local)} => #{path}/#{remote}"
|
80
|
+
end
|
81
|
+
|
82
|
+
global_size = 0
|
83
|
+
|
84
|
+
files.each_value do |file|
|
85
|
+
global_size += File.size(file)
|
86
|
+
end
|
87
|
+
|
88
|
+
global_size_kb = global_size / 1024
|
89
|
+
global_size_mb = global_size_kb / 1024
|
90
|
+
|
91
|
+
@log.info "#{files.size} files to upload (#{global_size_mb > 0 ? global_size_mb.to_s + "MB" : global_size_kb > 0 ? global_size_kb.to_s + "kB" : global_size.to_s})"
|
92
|
+
|
93
|
+
@ssh.sftp.connect do |sftp|
|
94
|
+
begin
|
95
|
+
sftp.stat!(path)
|
96
|
+
rescue Net::SFTP::StatusException => e
|
97
|
+
raise unless e.code == 2
|
98
|
+
@ssh.exec!("mkdir -p #{path}")
|
99
|
+
end
|
100
|
+
|
101
|
+
nb = 0
|
102
|
+
|
103
|
+
files.each do |key, local|
|
104
|
+
name = File.basename(local)
|
105
|
+
remote = "#{path}/#{key}"
|
106
|
+
size_b = File.size(local)
|
107
|
+
size_kb = size_b / 1024
|
108
|
+
nb_of = "#{nb += 1}/#{files.size}"
|
109
|
+
|
110
|
+
begin
|
111
|
+
sftp.stat!(remote)
|
112
|
+
|
113
|
+
unless @plugin_config['overwrite']
|
114
|
+
|
115
|
+
local_md5_sum = `md5sum #{local} | awk '{ print $1 }'`.strip
|
116
|
+
remote_md5_sum = @ssh.exec!("md5sum #{remote} | awk '{ print $1 }'").strip
|
117
|
+
|
118
|
+
if (local_md5_sum.eql?(remote_md5_sum))
|
119
|
+
@log.info "#{nb_of} #{name}: files are identical (md5sum: #{local_md5_sum}), skipping..."
|
120
|
+
next
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
rescue Net::SFTP::StatusException => e
|
125
|
+
raise unless e.code == 2
|
126
|
+
end
|
127
|
+
|
128
|
+
@ssh.exec!("mkdir -p #{File.dirname(remote) }")
|
129
|
+
|
130
|
+
pbar = ProgressBar.new("#{nb_of} #{name}", size_b)
|
131
|
+
pbar.file_transfer_mode
|
132
|
+
|
133
|
+
sftp.upload!(local, remote) do |event, uploader, * args|
|
134
|
+
case event
|
135
|
+
when :open then
|
136
|
+
when :put then
|
137
|
+
pbar.set(args[1])
|
138
|
+
when :close then
|
139
|
+
when :mkdir then
|
140
|
+
when :finish then
|
141
|
+
pbar.finish
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
sftp.setstat(remote, :permissions => @plugin_config['default_permissions'])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
plugin :class => BoxGrinder::SFTPPlugin, :type => :delivery, :name => :sftp, :full_name => "SSH File Transfer Protocol"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'boxgrinder-build/plugins/base-plugin'
|
20
|
+
|
21
|
+
module BoxGrinder
|
22
|
+
class USBPlugin < BasePlugin
|
23
|
+
def after_init
|
24
|
+
validate_plugin_config(['device' ])
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute( type = :usb )
|
28
|
+
validate_device
|
29
|
+
|
30
|
+
@log.debug "Using '#{@plugin_config['device']}' as a target device..."
|
31
|
+
@exec_helper.execute( "dd if=#{@previous_deliverables.disk} of=#{@plugin_config['device']} bs=1M" )
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_device
|
36
|
+
# check if this is USB
|
37
|
+
# see if it contains required space
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# plugin :class => BoxGrinder::USBPlugin, :type => :delivery, :name => :usb, :full_name => "USB"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'boxgrinder-build/plugins/os/rhel/rhel-plugin'
|
20
|
+
|
21
|
+
module BoxGrinder
|
22
|
+
class CentOSPlugin < RHELPlugin
|
23
|
+
|
24
|
+
CENTOS_REPOS = {
|
25
|
+
"5" => {
|
26
|
+
"base" => {
|
27
|
+
"mirrorlist" => "http://mirrorlist.centos.org/?release=#OS_VERSION#&arch=#BASE_ARCH#&repo=os"
|
28
|
+
},
|
29
|
+
"updates" => {
|
30
|
+
"mirrorlist" => "http://mirrorlist.centos.org/?release=#OS_VERSION#&arch=#BASE_ARCH#&repo=updates"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
def after_init
|
36
|
+
super
|
37
|
+
register_supported_os('centos', ['5'])
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute(appliance_definition_file)
|
41
|
+
build_rhel(appliance_definition_file, CENTOS_REPOS)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
plugin :class => BoxGrinder::CentOSPlugin, :type => :os, :name => :centos, :full_name => "CentOS", :versions => ["5"]
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin'
|
20
|
+
|
21
|
+
module BoxGrinder
|
22
|
+
class FedoraPlugin < RPMBasedOSPlugin
|
23
|
+
def after_init
|
24
|
+
super
|
25
|
+
register_supported_os('fedora', ["13", "14", "15", "rawhide"])
|
26
|
+
end
|
27
|
+
|
28
|
+
def execute(appliance_definition_file)
|
29
|
+
normalize_packages(@appliance_config.packages)
|
30
|
+
|
31
|
+
@repos = {}
|
32
|
+
|
33
|
+
@plugin_info[:versions].each do |version|
|
34
|
+
if version.match(/\d+/)
|
35
|
+
@repos[version] = {
|
36
|
+
"base" => {"mirrorlist" => "http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-#{version}&arch=#BASE_ARCH#"},
|
37
|
+
"updates" => {"mirrorlist" => "http://mirrors.fedoraproject.org/mirrorlist?repo=updates-released-f#{version}&arch=#BASE_ARCH#"}
|
38
|
+
}
|
39
|
+
else
|
40
|
+
@repos[version] = {"base" => {"mirrorlist" => "http://mirrors.fedoraproject.org/mirrorlist?repo=#{version}&arch=#BASE_ARCH#"}}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
build_with_appliance_creator(appliance_definition_file, @repos)
|
45
|
+
end
|
46
|
+
|
47
|
+
def normalize_packages(packages)
|
48
|
+
# https://issues.jboss.org/browse/BGBUILD-89
|
49
|
+
packages << '@core'
|
50
|
+
packages << "system-config-firewall-base"
|
51
|
+
packages << "dhclient"
|
52
|
+
|
53
|
+
# kernel_PAE for 32 bit, kernel for 64 bit
|
54
|
+
packages.delete('kernel')
|
55
|
+
packages.delete('kernel-PAE')
|
56
|
+
packages << (@appliance_config.is64bit? ? "kernel" : "kernel-PAE")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
plugin :class => BoxGrinder::FedoraPlugin, :type => :os, :name => :fedora, :full_name => "Fedora", :versions => ["13", "14", "15", "rawhide"]
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin'
|
20
|
+
|
21
|
+
module BoxGrinder
|
22
|
+
class RHELPlugin < RPMBasedOSPlugin
|
23
|
+
def after_init
|
24
|
+
super
|
25
|
+
register_supported_os('rhel', ['5', '6'])
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_rhel(appliance_definition_file, repos = {})
|
29
|
+
adjust_partition_table
|
30
|
+
|
31
|
+
normalize_packages(@appliance_config.packages)
|
32
|
+
|
33
|
+
build_with_appliance_creator(appliance_definition_file, repos) do |guestfs, guestfs_helper|
|
34
|
+
# required for VMware and KVM
|
35
|
+
@linux_helper.recreate_kernel_image(guestfs, ['mptspi', 'virtio_pci', 'virtio_blk']) if @appliance_config.os.version == '5' and !@appliance_config.packages.include?('kernel-xen')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def normalize_packages(packages)
|
40
|
+
# https://issues.jboss.org/browse/BGBUILD-89
|
41
|
+
add_packages(packages, ['@core', 'curl'])
|
42
|
+
|
43
|
+
case @appliance_config.os.version
|
44
|
+
when '5'
|
45
|
+
packages << 'kernel' unless packages.include?('kernel-xen')
|
46
|
+
add_packages(packages, ['system-config-securitylevel-tui', 'util-linux', 'setarch', 'sudo'])
|
47
|
+
when '6'
|
48
|
+
add_packages(packages, ['kernel', 'system-config-firewall-base'])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_packages(packages, package_array)
|
53
|
+
package_array.each { |package| packages << package unless packages.include?(package) }
|
54
|
+
end
|
55
|
+
|
56
|
+
# https://bugzilla.redhat.com/show_bug.cgi?id=466275
|
57
|
+
def adjust_partition_table
|
58
|
+
@appliance_config.hardware.partitions['/boot'] = {'root' => '/boot', 'type' => 'ext3', 'size' => 0.1} if @appliance_config.hardware.partitions['/boot'].nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
def execute(appliance_definition_file)
|
62
|
+
build_rhel(appliance_definition_file)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
plugin :class => BoxGrinder::RHELPlugin, :type => :os, :name => :rhel, :full_name => "Red Hat Enterprise Linux", :versions => ['5', '6']
|
@@ -0,0 +1,118 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'fileutils'
|
20
|
+
require 'yaml'
|
21
|
+
require 'erb'
|
22
|
+
|
23
|
+
module BoxGrinder
|
24
|
+
|
25
|
+
class Kickstart
|
26
|
+
def initialize(config, appliance_config, repos, dir, options = {})
|
27
|
+
@config = config
|
28
|
+
@repos = repos
|
29
|
+
@appliance_config = appliance_config
|
30
|
+
@dir = dir
|
31
|
+
@log = options[:log] || Logger.new(STDOUT)
|
32
|
+
|
33
|
+
@kickstart_file = "#{@dir.tmp}/#{@appliance_config.name}.ks"
|
34
|
+
end
|
35
|
+
|
36
|
+
def create
|
37
|
+
template = "#{File.dirname(__FILE__)}/src/appliance.ks.erb"
|
38
|
+
kickstart = ERB.new(File.read(template)).result(build_definition.send(:binding))
|
39
|
+
File.open(@kickstart_file, 'w') { |f| f.write(kickstart) }
|
40
|
+
|
41
|
+
@kickstart_file
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_definition
|
45
|
+
definition = {}
|
46
|
+
|
47
|
+
definition['appliance_config'] = @appliance_config
|
48
|
+
definition['repos'] = []
|
49
|
+
definition['graphical'] = (@appliance_config.packages.include?( '@base-x' ) or @appliance_config.packages.include?( '@X Window System' )) ? true : false
|
50
|
+
|
51
|
+
def definition.method_missing(sym, * args)
|
52
|
+
self[sym.to_s]
|
53
|
+
end
|
54
|
+
|
55
|
+
cost = 40
|
56
|
+
|
57
|
+
definition['partitions'] = @appliance_config.hardware.partitions
|
58
|
+
|
59
|
+
repos = []
|
60
|
+
repos += default_repos if @appliance_config.default_repos
|
61
|
+
repos += @appliance_config.repos
|
62
|
+
|
63
|
+
for repo in repos
|
64
|
+
if repo.keys.include?('mirrorlist')
|
65
|
+
urltype = 'mirrorlist'
|
66
|
+
else
|
67
|
+
urltype = 'baseurl'
|
68
|
+
end
|
69
|
+
|
70
|
+
substitutions = {
|
71
|
+
/#ARCH#/ => @appliance_config.hardware.arch,
|
72
|
+
/#BASE_ARCH#/ => @appliance_config.hardware.base_arch,
|
73
|
+
/#OS_VERSION#/ => @appliance_config.os.version,
|
74
|
+
/#OS_NAME#/ => @appliance_config.os.name
|
75
|
+
}
|
76
|
+
|
77
|
+
url = repo[urltype]
|
78
|
+
name = repo['name']
|
79
|
+
|
80
|
+
substitutions.each do |key, value|
|
81
|
+
url = url.gsub(key, value)
|
82
|
+
name = name.gsub(key, value)
|
83
|
+
end
|
84
|
+
|
85
|
+
definition['repos'] << "repo --name=#{name} --cost=#{cost} --#{urltype}=#{url}"
|
86
|
+
|
87
|
+
cost += 1
|
88
|
+
end
|
89
|
+
|
90
|
+
definition
|
91
|
+
end
|
92
|
+
|
93
|
+
def default_repos
|
94
|
+
os_repos = @repos[@appliance_config.os.version]
|
95
|
+
|
96
|
+
repos = Array.new
|
97
|
+
|
98
|
+
for type in ["base", "updates"]
|
99
|
+
unless os_repos.nil? or os_repos[type].nil?
|
100
|
+
|
101
|
+
mirrorlist = os_repos[type]['mirrorlist']
|
102
|
+
baseurl = os_repos[type]['baseurl']
|
103
|
+
|
104
|
+
name = "#{@appliance_config.os.name}-#{@appliance_config.os.version}-#{type}"
|
105
|
+
|
106
|
+
if mirrorlist.nil?
|
107
|
+
repos.push({"name" => name, "baseurl" => baseurl})
|
108
|
+
else
|
109
|
+
repos.push({"name" => name, "mirrorlist" => mirrorlist})
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
repos
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'boxgrinder-core/models/appliance-config'
|
20
|
+
require 'boxgrinder-build/plugins/base-plugin'
|
21
|
+
require 'boxgrinder-build/plugins/os/rpm-based/kickstart'
|
22
|
+
require 'boxgrinder-build/plugins/os/rpm-based/rpm-dependency-validator'
|
23
|
+
require 'boxgrinder-build/helpers/linux-helper'
|
24
|
+
|
25
|
+
module BoxGrinder
|
26
|
+
class RPMBasedOSPlugin < BasePlugin
|
27
|
+
def after_init
|
28
|
+
set_default_config_value('format', 'raw')
|
29
|
+
|
30
|
+
register_deliverable(
|
31
|
+
:disk => "#{@appliance_config.name}-sda.#{@plugin_config['format']}",
|
32
|
+
:descriptor => "#{@appliance_config.name}.xml"
|
33
|
+
)
|
34
|
+
|
35
|
+
@linux_helper = LinuxHelper.new(:log => @log)
|
36
|
+
end
|
37
|
+
|
38
|
+
def read_file(file)
|
39
|
+
read_kickstart(file) if File.extname(file).eql?('.ks')
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_kickstart(file)
|
43
|
+
appliance_config = ApplianceConfig.new
|
44
|
+
|
45
|
+
appliance_config.name = File.basename(file, '.ks')
|
46
|
+
|
47
|
+
name = nil
|
48
|
+
version = nil
|
49
|
+
|
50
|
+
File.read(file).each do |line|
|
51
|
+
n = line.scan(/^# bg_os_name: (.*)/).flatten.first
|
52
|
+
v = line.scan(/^# bg_os_version: (.*)/).flatten.first
|
53
|
+
|
54
|
+
name = n unless n.nil?
|
55
|
+
version = v unless v.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
raise "No operating system name specified, please add comment to you kickstrt file like this: # bg_os_name: fedora" if name.nil?
|
59
|
+
raise "No operating system version specified, please add comment to you kickstrt file like this: # bg_os_version: 14" if version.nil?
|
60
|
+
|
61
|
+
appliance_config.os.name = name
|
62
|
+
appliance_config.os.version = version
|
63
|
+
|
64
|
+
appliance_config
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_with_appliance_creator(appliance_definition_file, repos = {})
|
68
|
+
if File.extname(appliance_definition_file).eql?('.ks')
|
69
|
+
kickstart_file = appliance_definition_file
|
70
|
+
else
|
71
|
+
kickstart_file = Kickstart.new(@config, @appliance_config, repos, @dir, :log => @log).create
|
72
|
+
end
|
73
|
+
|
74
|
+
RPMDependencyValidator.new(@config, @appliance_config, @dir, kickstart_file, @options).resolve_packages
|
75
|
+
|
76
|
+
@log.info "Building #{@appliance_config.name} appliance..."
|
77
|
+
|
78
|
+
@exec_helper.execute "appliance-creator -d -v -t '#{@dir.tmp}' --cache=#{@config.dir.cache}/rpms-cache/#{@appliance_config.path.main} --config '#{kickstart_file}' -o '#{@dir.tmp}' --name '#{@appliance_config.name}' --vmem #{@appliance_config.hardware.memory} --vcpu #{@appliance_config.hardware.cpus} --format #{@plugin_config['format']}"
|
79
|
+
|
80
|
+
FileUtils.mv(Dir.glob("#{@dir.tmp}/#{@appliance_config.name}/*"), @dir.tmp)
|
81
|
+
FileUtils.rm_rf("#{@dir.tmp}/#{@appliance_config.name}/")
|
82
|
+
|
83
|
+
@image_helper.customize(@deliverables.disk) do |guestfs, guestfs_helper|
|
84
|
+
# TODO is this really needed?
|
85
|
+
@log.debug "Uploading '/etc/resolv.conf'..."
|
86
|
+
guestfs.upload("/etc/resolv.conf", "/etc/resolv.conf")
|
87
|
+
@log.debug "'/etc/resolv.conf' uploaded."
|
88
|
+
|
89
|
+
change_configuration(guestfs_helper)
|
90
|
+
# TODO check if this is still required
|
91
|
+
apply_root_password(guestfs)
|
92
|
+
fix_partition_labels(guestfs)
|
93
|
+
use_labels_for_partitions(guestfs)
|
94
|
+
disable_firewall(guestfs)
|
95
|
+
set_motd(guestfs)
|
96
|
+
install_repos(guestfs)
|
97
|
+
|
98
|
+
guestfs.sh("chkconfig firstboot off") if guestfs.exists('/etc/init.d/firstboot') != 0
|
99
|
+
|
100
|
+
@log.info "Executing post operations after build..."
|
101
|
+
|
102
|
+
unless @appliance_config.post['base'].nil?
|
103
|
+
@appliance_config.post['base'].each do |cmd|
|
104
|
+
guestfs_helper.sh(cmd, :arch => @appliance_config.hardware.arch)
|
105
|
+
end
|
106
|
+
@log.debug "Post commands from appliance definition file executed."
|
107
|
+
else
|
108
|
+
@log.debug "No commands specified, skipping."
|
109
|
+
end
|
110
|
+
|
111
|
+
yield guestfs, guestfs_helper if block_given?
|
112
|
+
|
113
|
+
@log.info "Post operations executed."
|
114
|
+
end
|
115
|
+
|
116
|
+
@log.info "Base image for #{@appliance_config.name} appliance was built successfully."
|
117
|
+
end
|
118
|
+
|
119
|
+
# https://issues.jboss.org/browse/BGBUILD-177
|
120
|
+
def disable_firewall(guestfs)
|
121
|
+
@log.debug "Disabling firewall..."
|
122
|
+
guestfs.sh("lokkit -q --disabled")
|
123
|
+
@log.debug "Firewall disabled."
|
124
|
+
end
|
125
|
+
|
126
|
+
def fix_partition_labels(guestfs)
|
127
|
+
guestfs.list_partitions.each do |partition|
|
128
|
+
guestfs.sh("/sbin/e2label #{partition} #{read_label(guestfs, partition)}")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def use_labels_for_partitions(guestfs)
|
133
|
+
device = guestfs.list_devices.first
|
134
|
+
|
135
|
+
# /etc/fstab
|
136
|
+
if fstab = guestfs.read_file('/etc/fstab').gsub!(/^(\/dev\/sda.)/) { |path| "LABEL=#{read_label(guestfs, path.gsub('/dev/sda', device))}" }
|
137
|
+
guestfs.write_file('/etc/fstab', fstab, 0)
|
138
|
+
end
|
139
|
+
|
140
|
+
# /boot/grub/grub.conf
|
141
|
+
if grub = guestfs.read_file('/boot/grub/grub.conf').gsub!(/(\/dev\/sda.)/) { |path| "LABEL=#{read_label(guestfs, path.gsub('/dev/sda', device))}" }
|
142
|
+
guestfs.write_file('/boot/grub/grub.conf', grub, 0)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def read_label(guestfs, partition)
|
147
|
+
(guestfs.respond_to?(:vfs_label) ? guestfs.vfs_label(partition) : guestfs.sh("/sbin/e2label #{partition}").chomp.strip).gsub('_', '')
|
148
|
+
end
|
149
|
+
|
150
|
+
def apply_root_password(guestfs)
|
151
|
+
@log.debug "Applying root password..."
|
152
|
+
guestfs.sh("/usr/bin/passwd -d root")
|
153
|
+
guestfs.sh("/usr/sbin/usermod -p '#{@appliance_config.os.password.crypt((0...8).map { 65.+(rand(25)).chr }.join)}' root")
|
154
|
+
@log.debug "Password applied."
|
155
|
+
end
|
156
|
+
|
157
|
+
def change_configuration(guestfs_helper)
|
158
|
+
guestfs_helper.augeas do
|
159
|
+
set('/etc/ssh/sshd_config', 'UseDNS', 'no')
|
160
|
+
set('/etc/sysconfig/selinux', 'SELINUX', 'permissive')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def set_motd(guestfs)
|
165
|
+
@log.debug "Setting up '/etc/motd'..."
|
166
|
+
# set nice banner for SSH
|
167
|
+
motd_file = "/etc/init.d/motd"
|
168
|
+
guestfs.upload("#{File.dirname(__FILE__)}/src/motd.init", motd_file)
|
169
|
+
guestfs.sh("sed -i s/#VERSION#/'#{@appliance_config.version}.#{@appliance_config.release}'/ #{motd_file}")
|
170
|
+
guestfs.sh("sed -i s/#APPLIANCE#/'#{@appliance_config.name} appliance'/ #{motd_file}")
|
171
|
+
|
172
|
+
guestfs.sh("/bin/chmod +x #{motd_file}")
|
173
|
+
guestfs.sh("/sbin/chkconfig --add motd")
|
174
|
+
@log.debug "'/etc/motd' is nice now."
|
175
|
+
end
|
176
|
+
|
177
|
+
def recreate_kernel_image(guestfs, modules = [])
|
178
|
+
@linux_helper.recreate_kernel_image(guestfs, modules)
|
179
|
+
end
|
180
|
+
|
181
|
+
def install_repos(guestfs)
|
182
|
+
@log.debug "Installing repositories from appliance definition file..."
|
183
|
+
@appliance_config.repos.each do |repo|
|
184
|
+
if repo['ephemeral']
|
185
|
+
@log.debug "Repository '#{repo['name']}' is an ephemeral repo. It'll not be installed in the appliance."
|
186
|
+
next
|
187
|
+
end
|
188
|
+
|
189
|
+
@log.debug "Installing #{repo['name']} repo..."
|
190
|
+
repo_file = File.read("#{File.dirname(__FILE__)}/src/base.repo").gsub(/#NAME#/, repo['name'])
|
191
|
+
|
192
|
+
['baseurl', 'mirrorlist'].each do |type|
|
193
|
+
repo_file << ("#{type}=#{repo[type]}\n") unless repo[type].nil?
|
194
|
+
end
|
195
|
+
|
196
|
+
guestfs.write_file("/etc/yum.repos.d/#{repo['name']}.repo", repo_file, 0)
|
197
|
+
end
|
198
|
+
@log.debug "Repositories installed."
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|