boxgrinder-build 0.4.1 → 0.5.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/CHANGELOG +7 -0
- data/Manifest +0 -0
- data/Rakefile +11 -0
- data/bin/boxgrinder-build +33 -27
- data/boxgrinder-build.gemspec +38 -0
- data/lib/boxgrinder-build/appliance.rb +32 -41
- data/lib/boxgrinder-build/helpers/appliance-customize-helper.rb +3 -48
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +98 -12
- data/lib/boxgrinder-build/helpers/linux-helper.rb +69 -0
- data/lib/boxgrinder-build/helpers/package-helper.rb +20 -11
- data/lib/boxgrinder-build/helpers/plugin-helper.rb +32 -32
- data/lib/boxgrinder-build/managers/plugin-manager.rb +98 -0
- data/lib/boxgrinder-build/plugins/base-plugin.rb +70 -17
- data/spec/Rakefile +13 -0
- data/spec/appliance-spec.rb +195 -0
- data/spec/helpers/appliance-customize-helper-spec.rb +30 -0
- data/spec/helpers/guestfs-helper-spec.rb +129 -0
- data/spec/helpers/linux-helper-spec.rb +50 -0
- data/spec/helpers/package-helper-spec.rb +6 -0
- data/spec/helpers/plugin-helper-spec.rb +63 -0
- data/spec/managers/plugin-manager-spec.rb +27 -0
- data/spec/plugins/base-plugin-spec.rb +89 -0
- data/spec/rspec/src/appliances/jeos-f13.appl +27 -0
- metadata +60 -157
- data/docs/examples/appliances/appliances.appl +0 -5
- data/docs/examples/appliances/minimal.appl +0 -9
- data/docs/examples/appliances/mix.appl +0 -8
- data/docs/examples/appliances/packages.appl +0 -13
- data/docs/node-info/pom.xml +0 -31
- data/docs/node-info/src/main/webapp/META-INF/MANIFEST.MF +0 -3
- data/docs/node-info/src/main/webapp/WEB-INF/web.xml +0 -7
- data/docs/node-info/src/main/webapp/index.jsp +0 -70
- data/lib/boxgrinder-build/helpers/rake-helper.rb +0 -71
- data/lib/boxgrinder-build/managers/base-plugin-manager.rb +0 -62
- data/lib/boxgrinder-build/managers/delivery-plugin-manager.rb +0 -39
- data/lib/boxgrinder-build/managers/operating-system-plugin-manager.rb +0 -6
- data/lib/boxgrinder-build/managers/platform-plugin-manager.rb +0 -26
- data/lib/boxgrinder-build/plugins/delivery/base/base-delivery-plugin.rb +0 -43
- data/lib/boxgrinder-build/plugins/delivery/local/local-plugin.rb +0 -57
- data/lib/boxgrinder-build/plugins/delivery/s3/aws-helper.rb +0 -64
- data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +0 -190
- data/lib/boxgrinder-build/plugins/delivery/sftp/sftp-plugin.rb +0 -159
- data/lib/boxgrinder-build/plugins/os/base/kickstart.rb +0 -148
- data/lib/boxgrinder-build/plugins/os/base/rhel-based-os-plugin.rb +0 -51
- data/lib/boxgrinder-build/plugins/os/base/rpm-based-os-plugin.rb +0 -134
- data/lib/boxgrinder-build/plugins/os/base/src/appliance.ks.erb +0 -41
- data/lib/boxgrinder-build/plugins/os/base/src/base.repo +0 -4
- data/lib/boxgrinder-build/plugins/os/base/src/motd.init +0 -21
- data/lib/boxgrinder-build/plugins/os/base/validators/rpm-dependency-validator.rb +0 -162
- data/lib/boxgrinder-build/plugins/os/base-operating-system-plugin.rb +0 -37
- data/lib/boxgrinder-build/plugins/os/centos/centos-plugin.rb +0 -52
- data/lib/boxgrinder-build/plugins/os/fedora/fedora-plugin.rb +0 -74
- data/lib/boxgrinder-build/plugins/os/rhel/rhel-plugin.rb +0 -40
- data/lib/boxgrinder-build/plugins/platform/base-platform-plugin.rb +0 -37
- data/lib/boxgrinder-build/plugins/platform/ec2/ec2-plugin.rb +0 -332
- data/lib/boxgrinder-build/plugins/platform/ec2/src/f12/yum.conf +0 -24
- data/lib/boxgrinder-build/plugins/platform/ec2/src/f12-i386-boxgrinder.repo +0 -11
- data/lib/boxgrinder-build/plugins/platform/ec2/src/f12-x86_64-boxgrinder.repo +0 -11
- data/lib/boxgrinder-build/plugins/platform/ec2/src/fstab_32bit +0 -8
- data/lib/boxgrinder-build/plugins/platform/ec2/src/fstab_64bit +0 -8
- data/lib/boxgrinder-build/plugins/platform/ec2/src/ifcfg-eth0 +0 -7
- data/lib/boxgrinder-build/plugins/platform/ec2/src/rc_local +0 -29
- data/lib/boxgrinder-build/plugins/platform/vmware/src/README +0 -42
- data/lib/boxgrinder-build/plugins/platform/vmware/src/base.vmdk +0 -19
- data/lib/boxgrinder-build/plugins/platform/vmware/src/base.vmx +0 -45
- data/lib/boxgrinder-build/plugins/platform/vmware/vmware-plugin.rb +0 -181
- data/lib/boxgrinder-build/validators/appliance-config-parameter-validator.rb +0 -37
- data/lib/boxgrinder-build/validators/appliance-validator.rb +0 -84
- data/lib/boxgrinder-build/validators/config-validator.rb +0 -48
- data/lib/boxgrinder-build/validators/ssh-validator.rb +0 -35
- data/lib/boxgrinder-build/validators/validator.rb +0 -91
@@ -1,190 +0,0 @@
|
|
1
|
-
# JBoss, Home of Professional Open Source
|
2
|
-
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
-
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
-
# full listing of individual contributors.
|
5
|
-
#
|
6
|
-
# This is free software; you can redistribute it and/or modify it
|
7
|
-
# under the terms of the GNU Lesser General Public License as
|
8
|
-
# published by the Free Software Foundation; either version 2.1 of
|
9
|
-
# the License, or (at your option) any later version.
|
10
|
-
#
|
11
|
-
# This software is distributed in the hope that it will be useful,
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
-
# Lesser General Public License for more details.
|
15
|
-
#
|
16
|
-
# You should have received a copy of the GNU Lesser General Public
|
17
|
-
# License along with this software; if not, write to the Free
|
18
|
-
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
-
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
-
|
21
|
-
require 'boxgrinder-build/plugins/delivery/base/base-delivery-plugin'
|
22
|
-
require 'boxgrinder-build/plugins/delivery/s3/aws-helper'
|
23
|
-
require 'AWS'
|
24
|
-
require 'aws/s3'
|
25
|
-
include AWS::S3
|
26
|
-
|
27
|
-
module BoxGrinder
|
28
|
-
class S3Plugin < BaseDeliveryPlugin
|
29
|
-
|
30
|
-
AMI_OSES = {
|
31
|
-
'fedora' => [ '11' ],
|
32
|
-
'centos' => [ '5' ],
|
33
|
-
'rhel' => [ '5' ]
|
34
|
-
}
|
35
|
-
|
36
|
-
KERNELS = {
|
37
|
-
'us_east' => {
|
38
|
-
'fedora' => {
|
39
|
-
'11' => {
|
40
|
-
'i386' => { :aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc' },
|
41
|
-
'x86_64' => { :aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da' }
|
42
|
-
}
|
43
|
-
},
|
44
|
-
'centos' => {
|
45
|
-
'5' => {
|
46
|
-
'i386' => { :aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc' },
|
47
|
-
'x86_64' => { :aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da' }
|
48
|
-
}
|
49
|
-
},
|
50
|
-
'rhel' => {
|
51
|
-
'5' => {
|
52
|
-
'i386' => { :aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc' },
|
53
|
-
'x86_64' => { :aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da' }
|
54
|
-
}
|
55
|
-
# '5' => {
|
56
|
-
# 'i386' => { :aki => 'aki-e3a54b8a', :ari => 'ari-f9a54b90' },
|
57
|
-
# 'x86_64' => { :aki => 'aki-ffa54b96', :ari => 'ari-fda54b94' }
|
58
|
-
# }
|
59
|
-
|
60
|
-
}
|
61
|
-
}
|
62
|
-
}
|
63
|
-
|
64
|
-
def info
|
65
|
-
{
|
66
|
-
:name => :s3,
|
67
|
-
:type => [:cloudfront, :ami, :s3],
|
68
|
-
:full_name => "Amazon Simple Storage Service (Amazon S3)"
|
69
|
-
}
|
70
|
-
end
|
71
|
-
|
72
|
-
def after_init
|
73
|
-
set_default_config_value('overwrite', false)
|
74
|
-
set_default_config_value('path', '/')
|
75
|
-
|
76
|
-
@ami_build_dir = "#{@appliance_config.path.dir.build}/ec2/ami"
|
77
|
-
@ami_manifest = "#{@ami_build_dir}/#{@appliance_config.name}.ec2.manifest.xml"
|
78
|
-
end
|
79
|
-
|
80
|
-
def supported_os
|
81
|
-
supported = ""
|
82
|
-
|
83
|
-
AMI_OSES.each_key do |os_name|
|
84
|
-
supported << "#{os_name}, versions: #{AMI_OSES[os_name].join(", ")}"
|
85
|
-
end
|
86
|
-
|
87
|
-
supported
|
88
|
-
end
|
89
|
-
|
90
|
-
def execute( deliverables, type = :ami )
|
91
|
-
validate_plugin_config(['bucket', 'access_key', 'secret_access_key'])
|
92
|
-
|
93
|
-
@aws_helper = AWSHelper.new( @config, @appliance_config, @plugin_config )
|
94
|
-
|
95
|
-
case type
|
96
|
-
when :s3
|
97
|
-
upload_to_bucket(deliverables)
|
98
|
-
when :cloudfront
|
99
|
-
upload_to_bucket(deliverables, :public_read)
|
100
|
-
when :ami
|
101
|
-
validate_plugin_config(['cert_file', 'key_file', 'account_number'])
|
102
|
-
|
103
|
-
unless AMI_OSES[@appliance_config.os.name].include?(@appliance_config.os.version)
|
104
|
-
@log.error "You cannot convert selected image to AMI because of unsupported operating system: #{@appliance_config.os.name} #{@appliance_config.os.version}. Supported systems: #{supported_os}."
|
105
|
-
return
|
106
|
-
end
|
107
|
-
|
108
|
-
unless image_already_uploaded?
|
109
|
-
bundle_image( deliverables )
|
110
|
-
upload_image
|
111
|
-
else
|
112
|
-
@log.debug "AMI for #{@appliance_config.name} appliance already uploaded, skipping..."
|
113
|
-
end
|
114
|
-
|
115
|
-
register_image
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def upload_to_bucket(deliverables, permissions = :private)
|
120
|
-
package = PackageHelper.new(@config, @appliance_config, {:log => @log, :exec_helper => @exec_helper}).package(deliverables)
|
121
|
-
|
122
|
-
@log.info "Uploading #{@appliance_config.name} appliance to S3 bucket '#{@plugin_config['bucket']}'..."
|
123
|
-
|
124
|
-
begin
|
125
|
-
AWS::S3::Bucket.find(@plugin_config['bucket'])
|
126
|
-
rescue AWS::S3::NoSuchBucket
|
127
|
-
AWS::S3::Bucket.create(@plugin_config['bucket'])
|
128
|
-
retry
|
129
|
-
end
|
130
|
-
|
131
|
-
remote_path = "#{@plugin_config['path']}/#{File.basename(package)}"
|
132
|
-
size_b = File.size(package)
|
133
|
-
|
134
|
-
unless S3Object.exists?(remote_path, @plugin_config['bucket']) or @plugin_config['overwrite']
|
135
|
-
@log.info "Uploading #{File.basename(package)} (#{size_b/1024/1024}MB)..."
|
136
|
-
AWS::S3::S3Object.store(remote_path, open(package), @plugin_config['bucket'], :access => permissions)
|
137
|
-
end
|
138
|
-
|
139
|
-
@log.info "Appliance #{@appliance_config.name} uploaded to S3."
|
140
|
-
end
|
141
|
-
|
142
|
-
|
143
|
-
def bundle_image( deliverables )
|
144
|
-
return if File.exists?( @ami_build_dir )
|
145
|
-
|
146
|
-
@log.info "Bundling AMI..."
|
147
|
-
|
148
|
-
FileUtils.mkdir_p( @ami_build_dir )
|
149
|
-
|
150
|
-
@exec_helper.execute("ec2-bundle-image -i #{deliverables[:disk]} --kernel #{KERNELS['us_east'][@appliance_config.os.name][@appliance_config.os.version][@appliance_config.hardware.arch][:aki]} --ramdisk #{KERNELS['us_east'][@appliance_config.os.name][@appliance_config.os.version][@appliance_config.hardware.arch][:ari]} -c #{@plugin_config['cert_file']} -k #{@plugin_config['key_file']} -u #{@plugin_config['account_number']} -r #{@appliance_config.hardware.arch} -d #{@ami_build_dir}")
|
151
|
-
|
152
|
-
@log.info "Bundling AMI finished."
|
153
|
-
end
|
154
|
-
|
155
|
-
def image_already_uploaded?
|
156
|
-
begin
|
157
|
-
bucket = Bucket.find(@plugin_config['bucket'])
|
158
|
-
rescue
|
159
|
-
return false
|
160
|
-
end
|
161
|
-
|
162
|
-
manifest_location = @aws_helper.bucket_manifest_key(@appliance_config.name, @plugin_config['path'])
|
163
|
-
manifest_location = manifest_location[manifest_location.index("/") + 1, manifest_location.length]
|
164
|
-
|
165
|
-
for object in bucket.objects do
|
166
|
-
return true if object.key.eql?(manifest_location)
|
167
|
-
end
|
168
|
-
|
169
|
-
false
|
170
|
-
end
|
171
|
-
|
172
|
-
def upload_image
|
173
|
-
@log.info "Uploading #{@appliance_config.name} AMI to bucket '#{@plugin_config['bucket']}'..."
|
174
|
-
|
175
|
-
@exec_helper.execute("ec2-upload-bundle -b #{@aws_helper.bucket_key(@appliance_config.name, @plugin_config['path'])} -m #{@ami_manifest} -a #{@plugin_config['access_key']} -s #{@plugin_config['secret_access_key']} --retry")
|
176
|
-
end
|
177
|
-
|
178
|
-
def register_image
|
179
|
-
ami_info = @aws_helper.ami_info(@appliance_config.name, @plugin_config['path'])
|
180
|
-
|
181
|
-
if ami_info
|
182
|
-
@log.info "Image is registered under id: #{ami_info.imageId}"
|
183
|
-
return
|
184
|
-
else
|
185
|
-
ami_info = @aws_helper.ec2.register_image(:image_location => @aws_helper.bucket_manifest_key(@appliance_config.name, @plugin_config['path']))
|
186
|
-
@log.info "Image successfully registered under id: #{ami_info.imageId}."
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
@@ -1,159 +0,0 @@
|
|
1
|
-
# JBoss, Home of Professional Open Source
|
2
|
-
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
-
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
-
# full listing of individual contributors.
|
5
|
-
#
|
6
|
-
# This is free software; you can redistribute it and/or modify it
|
7
|
-
# under the terms of the GNU Lesser General Public License as
|
8
|
-
# published by the Free Software Foundation; either version 2.1 of
|
9
|
-
# the License, or (at your option) any later version.
|
10
|
-
#
|
11
|
-
# This software is distributed in the hope that it will be useful,
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
-
# Lesser General Public License for more details.
|
15
|
-
#
|
16
|
-
# You should have received a copy of the GNU Lesser General Public
|
17
|
-
# License along with this software; if not, write to the Free
|
18
|
-
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
-
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
-
|
21
|
-
require 'net/ssh'
|
22
|
-
require 'net/sftp'
|
23
|
-
require 'progressbar'
|
24
|
-
require 'boxgrinder-build/plugins/delivery/base/base-delivery-plugin'
|
25
|
-
require 'boxgrinder-build/helpers/package-helper'
|
26
|
-
|
27
|
-
module BoxGrinder
|
28
|
-
class SFTPPlugin < BaseDeliveryPlugin
|
29
|
-
def info
|
30
|
-
{
|
31
|
-
:name => :sftp,
|
32
|
-
:type => [:sftp],
|
33
|
-
:full_name => "SSH File Transfer Protocol"
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
def after_init
|
38
|
-
set_default_config_value('overwrite', false)
|
39
|
-
set_default_config_value('default_permissions', 0644)
|
40
|
-
end
|
41
|
-
|
42
|
-
def execute(deliverables, type = :sftp)
|
43
|
-
validate_plugin_config(['path', 'username', 'host'], 'CHANGEME')
|
44
|
-
|
45
|
-
#SSHValidator.new( @config ).validate
|
46
|
-
|
47
|
-
package = PackageHelper.new(@config, @appliance_config, {:log => @log, :exec_helper => @exec_helper}).package(deliverables)
|
48
|
-
|
49
|
-
@log.info "Uploading #{@appliance_config.name} appliance via SSH..."
|
50
|
-
|
51
|
-
begin
|
52
|
-
#TODO move to a block
|
53
|
-
connect
|
54
|
-
upload_files(@plugin_config['path'], {File.basename(package) => package})
|
55
|
-
disconnect
|
56
|
-
|
57
|
-
@log.info "Appliance #{@appliance_config.name} uploaded."
|
58
|
-
rescue => e
|
59
|
-
@log.error e
|
60
|
-
@log.error "An error occurred while uploading files."
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def connect
|
65
|
-
@log.info "Connecting to #{@plugin_config['host']}..."
|
66
|
-
@ssh = Net::SSH.start(@plugin_config['host'], @plugin_config['username'], {:password => @plugin_config['password']})
|
67
|
-
end
|
68
|
-
|
69
|
-
def connected?
|
70
|
-
return true if !@ssh.nil? and !@ssh.closed?
|
71
|
-
false
|
72
|
-
end
|
73
|
-
|
74
|
-
def disconnect
|
75
|
-
@log.info "Disconnecting from #{@plugin_config['host']}..."
|
76
|
-
@ssh.close if connected?
|
77
|
-
@ssh = nil
|
78
|
-
end
|
79
|
-
|
80
|
-
def upload_files(path, files = {})
|
81
|
-
return if files.size == 0
|
82
|
-
|
83
|
-
raise "You're not connected to server" unless connected?
|
84
|
-
|
85
|
-
@log.debug "Files to upload:"
|
86
|
-
|
87
|
-
files.each do |remote, local|
|
88
|
-
@log.debug "#{local} => #{remote}"
|
89
|
-
end
|
90
|
-
|
91
|
-
global_size = 0
|
92
|
-
|
93
|
-
files.each_value do |file|
|
94
|
-
global_size += File.size(file)
|
95
|
-
end
|
96
|
-
|
97
|
-
global_size_kb = global_size / 1024
|
98
|
-
global_size_mb = global_size_kb / 1024
|
99
|
-
|
100
|
-
@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})"
|
101
|
-
|
102
|
-
@ssh.sftp.connect do |sftp|
|
103
|
-
begin
|
104
|
-
sftp.stat!(path)
|
105
|
-
rescue Net::SFTP::StatusException => e
|
106
|
-
raise unless e.code == 2
|
107
|
-
@ssh.exec!("mkdir -p #{path}")
|
108
|
-
end
|
109
|
-
|
110
|
-
nb = 0
|
111
|
-
|
112
|
-
files.each do |key, local|
|
113
|
-
name = File.basename(local)
|
114
|
-
remote = "#{path}/#{key}"
|
115
|
-
size_b = File.size(local)
|
116
|
-
size_kb = size_b / 1024
|
117
|
-
nb_of = "#{nb += 1}/#{files.size}"
|
118
|
-
|
119
|
-
begin
|
120
|
-
sftp.stat!(remote)
|
121
|
-
|
122
|
-
unless @plugin_config['overwrite']
|
123
|
-
|
124
|
-
local_md5_sum = `md5sum #{local} | awk '{ print $1 }'`.strip
|
125
|
-
remote_md5_sum = @ssh.exec!("md5sum #{remote} | awk '{ print $1 }'").strip
|
126
|
-
|
127
|
-
if (local_md5_sum.eql?(remote_md5_sum))
|
128
|
-
@log.info "#{nb_of} #{name}: files are identical (md5sum: #{local_md5_sum}), skipping..."
|
129
|
-
next
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
rescue Net::SFTP::StatusException => e
|
134
|
-
raise unless e.code == 2
|
135
|
-
end
|
136
|
-
|
137
|
-
@ssh.exec!("mkdir -p #{File.dirname(remote) }")
|
138
|
-
|
139
|
-
pbar = ProgressBar.new("#{nb_of} #{name}", size_b)
|
140
|
-
pbar.file_transfer_mode
|
141
|
-
|
142
|
-
sftp.upload!(local, remote) do |event, uploader, * args|
|
143
|
-
case event
|
144
|
-
when :open then
|
145
|
-
when :put then
|
146
|
-
pbar.set(args[1])
|
147
|
-
when :close then
|
148
|
-
when :mkdir then
|
149
|
-
when :finish then
|
150
|
-
pbar.finish
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
sftp.setstat(remote, :permissions => @plugin_config['default_permissions'])
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
@@ -1,148 +0,0 @@
|
|
1
|
-
# JBoss, Home of Professional Open Source
|
2
|
-
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
-
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
-
# full listing of individual contributors.
|
5
|
-
#
|
6
|
-
# This is free software; you can redistribute it and/or modify it
|
7
|
-
# under the terms of the GNU Lesser General Public License as
|
8
|
-
# published by the Free Software Foundation; either version 2.1 of
|
9
|
-
# the License, or (at your option) any later version.
|
10
|
-
#
|
11
|
-
# This software is distributed in the hope that it will be useful,
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
-
# Lesser General Public License for more details.
|
15
|
-
#
|
16
|
-
# You should have received a copy of the GNU Lesser General Public
|
17
|
-
# License along with this software; if not, write to the Free
|
18
|
-
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
-
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
-
|
21
|
-
require 'fileutils'
|
22
|
-
require 'yaml'
|
23
|
-
require 'erb'
|
24
|
-
|
25
|
-
module BoxGrinder
|
26
|
-
|
27
|
-
class Kickstart
|
28
|
-
|
29
|
-
def initialize(config, appliance_config, repos, options = {})
|
30
|
-
@config = config
|
31
|
-
@repos = repos
|
32
|
-
@appliance_config = appliance_config
|
33
|
-
@log = options[:log] || Logger.new(STDOUT)
|
34
|
-
end
|
35
|
-
|
36
|
-
def create
|
37
|
-
FileUtils.mkdir_p @appliance_config.path.dir.raw.build
|
38
|
-
|
39
|
-
template = "#{File.dirname(__FILE__)}/src/appliance.ks.erb"
|
40
|
-
kickstart = ERB.new(File.read(template)).result(build_definition.send(:binding))
|
41
|
-
File.open(@appliance_config.path.file.raw.kickstart, 'w') { |f| f.write(kickstart) }
|
42
|
-
end
|
43
|
-
|
44
|
-
def build_definition
|
45
|
-
definition = {}
|
46
|
-
|
47
|
-
definition['appliance_config'] = @appliance_config
|
48
|
-
|
49
|
-
#definition['partitions'] = @appliance_config.hardware.partitions.values
|
50
|
-
definition['name'] = @appliance_config.name
|
51
|
-
definition['arch'] = @appliance_config.hardware.arch
|
52
|
-
definition['appliance_names'] = @appliance_config.appliances
|
53
|
-
definition['repos'] = []
|
54
|
-
|
55
|
-
# appliance_definition = @image_config.definition
|
56
|
-
#
|
57
|
-
# if SUPPORTED_DESKTOP_TYPES.include?( appliance_definition['desktop'] )
|
58
|
-
# definition['graphical'] = true
|
59
|
-
#
|
60
|
-
# # default X package groups
|
61
|
-
# definition['packages'] = [ "@base-x", "@base", "@core", "@fonts", "@input-methods", "@admin-tools", "@dial-up", "@hardware-support", "@printing" ]
|
62
|
-
#
|
63
|
-
# #selected desktop environment
|
64
|
-
# definition['packages'] += [ "@#{appliance_definition['desktop']}-desktop" ]
|
65
|
-
# else
|
66
|
-
# definition['graphical'] = false
|
67
|
-
# definition['packages'] = []
|
68
|
-
# end
|
69
|
-
|
70
|
-
definition['graphical'] = false
|
71
|
-
definition['packages'] = []
|
72
|
-
|
73
|
-
definition['packages'] += @appliance_config.packages.includes
|
74
|
-
|
75
|
-
@appliance_config.packages.excludes do |package|
|
76
|
-
definition['packages'].push("-#{package}")
|
77
|
-
end
|
78
|
-
|
79
|
-
# defautlt filesystem
|
80
|
-
definition['fstype'] = "ext3"
|
81
|
-
|
82
|
-
# fix for F12; this is needed because of selinux management in appliance-creator
|
83
|
-
if @appliance_config.os.name.eql?("fedora")
|
84
|
-
definition['packages'].push("kernel", "passwd")
|
85
|
-
case @appliance_config.os.version.to_s
|
86
|
-
when "12" then
|
87
|
-
definition['packages'].push "system-config-firewall-base"
|
88
|
-
# default filesystem for fedora 12
|
89
|
-
#definition['fstype'] = "ext4"
|
90
|
-
when "11" then
|
91
|
-
definition['packages'].push "lokkit"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
definition['root_password'] = @appliance_config.os.password
|
96
|
-
|
97
|
-
def definition.method_missing(sym, * args)
|
98
|
-
self[sym.to_s]
|
99
|
-
end
|
100
|
-
|
101
|
-
cost = 40
|
102
|
-
|
103
|
-
for repo in valid_repos + @appliance_config.repos
|
104
|
-
if repo.keys.include?('mirrorlist')
|
105
|
-
urltype = 'mirrorlist'
|
106
|
-
else
|
107
|
-
urltype = 'baseurl'
|
108
|
-
end
|
109
|
-
|
110
|
-
url = repo[urltype].gsub(/#ARCH#/, @appliance_config.hardware.arch).gsub(/#OS_VERSION#/, @appliance_config.os.version).gsub(/#OS_NAME#/, @appliance_config.os.name)
|
111
|
-
|
112
|
-
repo_def = "repo --name=#{repo['name']} --cost=#{cost} --#{urltype}=#{url}"
|
113
|
-
repo_def += " --excludepkgs=#{repo['excludes'].join(',')}" unless repo['excludes'].nil? or repo['excludes'].empty?
|
114
|
-
|
115
|
-
definition['repos'] << repo_def
|
116
|
-
|
117
|
-
cost += 1
|
118
|
-
end
|
119
|
-
|
120
|
-
definition
|
121
|
-
end
|
122
|
-
|
123
|
-
def valid_repos
|
124
|
-
os_repos = @repos[@appliance_config.os.version]
|
125
|
-
|
126
|
-
repos = Array.new
|
127
|
-
|
128
|
-
for type in ["base", "updates"]
|
129
|
-
unless os_repos.nil? or os_repos[type].nil?
|
130
|
-
|
131
|
-
mirrorlist = os_repos[type]['mirrorlist']
|
132
|
-
baseurl = os_repos[type]['baseurl']
|
133
|
-
|
134
|
-
name = "#{@appliance_config.os.name}-#{@appliance_config.os.version}-#{type}"
|
135
|
-
|
136
|
-
if mirrorlist.nil?
|
137
|
-
repos.push({"name" => name, "baseurl" => baseurl})
|
138
|
-
else
|
139
|
-
repos.push({"name" => name, "mirrorlist" => mirrorlist})
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
repos
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# JBoss, Home of Professional Open Source
|
2
|
-
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
-
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
-
# full listing of individual contributors.
|
5
|
-
#
|
6
|
-
# This is free software; you can redistribute it and/or modify it
|
7
|
-
# under the terms of the GNU Lesser General Public License as
|
8
|
-
# published by the Free Software Foundation; either version 2.1 of
|
9
|
-
# the License, or (at your option) any later version.
|
10
|
-
#
|
11
|
-
# This software is distributed in the hope that it will be useful,
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
-
# Lesser General Public License for more details.
|
15
|
-
#
|
16
|
-
# You should have received a copy of the GNU Lesser General Public
|
17
|
-
# License along with this software; if not, write to the Free
|
18
|
-
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
-
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
-
|
21
|
-
require 'boxgrinder-build/plugins/os/base/rpm-based-os-plugin'
|
22
|
-
|
23
|
-
module BoxGrinder
|
24
|
-
class RHELBasedOSPlugin < RPMBasedOSPlugin
|
25
|
-
def build_rhel( repos = {} )
|
26
|
-
adjust_partition_table
|
27
|
-
|
28
|
-
disk_path = build_with_appliance_creator( repos ) do |guestfs, guestfs_helper|
|
29
|
-
kernel_version = guestfs.ls("/lib/modules").first
|
30
|
-
|
31
|
-
@log.debug "Recreating initrd for #{kernel_version} kernel..."
|
32
|
-
guestfs.sh( "/sbin/mkinitrd -f -v --preload=mptspi /boot/initrd-#{kernel_version}.img #{kernel_version}" )
|
33
|
-
@log.debug "Initrd recreated."
|
34
|
-
|
35
|
-
@log.debug "Applying root password..."
|
36
|
-
guestfs.sh( "/usr/bin/passwd -d root" )
|
37
|
-
guestfs.sh( "/usr/sbin/usermod -p '#{@appliance_config.os.password.crypt((0...8).map{65.+(rand(25)).chr}.join)}' root" )
|
38
|
-
@log.debug "Password applied."
|
39
|
-
end
|
40
|
-
|
41
|
-
@log.info "Done."
|
42
|
-
|
43
|
-
disk_path
|
44
|
-
end
|
45
|
-
|
46
|
-
# https://bugzilla.redhat.com/show_bug.cgi?id=466275
|
47
|
-
def adjust_partition_table
|
48
|
-
@appliance_config.hardware.partitions['/boot'] = { 'root' => '/boot', 'size' => 0.1 } if @appliance_config.hardware.partitions['/boot'].nil?
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,134 +0,0 @@
|
|
1
|
-
# JBoss, Home of Professional Open Source
|
2
|
-
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
-
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
-
# full listing of individual contributors.
|
5
|
-
#
|
6
|
-
# This is free software; you can redistribute it and/or modify it
|
7
|
-
# under the terms of the GNU Lesser General Public License as
|
8
|
-
# published by the Free Software Foundation; either version 2.1 of
|
9
|
-
# the License, or (at your option) any later version.
|
10
|
-
#
|
11
|
-
# This software is distributed in the hope that it will be useful,
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
-
# Lesser General Public License for more details.
|
15
|
-
#
|
16
|
-
# You should have received a copy of the GNU Lesser General Public
|
17
|
-
# License along with this software; if not, write to the Free
|
18
|
-
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
-
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
-
|
21
|
-
require 'boxgrinder-build/plugins/os/base-operating-system-plugin'
|
22
|
-
|
23
|
-
module BoxGrinder
|
24
|
-
class RPMBasedOSPlugin < BaseOperatingSystemPlugin
|
25
|
-
def after_init
|
26
|
-
@deliverables[:disk] = "#{@appliance_config.path.dir.raw.build_full}/#{@appliance_config.name}-sda.raw"
|
27
|
-
|
28
|
-
@deliverables[:metadata] = {
|
29
|
-
:descriptor => "#{@appliance_config.path.dir.raw.build_full}/#{@appliance_config.name}.xml"
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
33
|
-
def build_with_appliance_creator( repos = {} )
|
34
|
-
Kickstart.new( @config, @appliance_config, repos, :log => @log ).create
|
35
|
-
RPMDependencyValidator.new( @config, @appliance_config, @options ).resolve_packages
|
36
|
-
|
37
|
-
tmp_dir = "#{@config.dir.root}/#{@config.dir.build}/tmp"
|
38
|
-
FileUtils.mkdir_p( tmp_dir )
|
39
|
-
|
40
|
-
@log.info "Building #{@appliance_config.name} appliance..."
|
41
|
-
|
42
|
-
@exec_helper.execute "sudo appliance-creator -d -v -t #{tmp_dir} --cache=#{@config.dir.rpms_cache}/#{@appliance_config.main_path} --config #{@appliance_config.path.file.raw.kickstart} -o #{@appliance_config.path.dir.raw.build} --name #{@appliance_config.name} --vmem #{@appliance_config.hardware.memory} --vcpu #{@appliance_config.hardware.cpus}"
|
43
|
-
|
44
|
-
# fix permissions
|
45
|
-
@exec_helper.execute "sudo chmod 777 #{@appliance_config.path.dir.raw.build_full}"
|
46
|
-
@exec_helper.execute "sudo chmod 666 #{@deliverables[:disk]}"
|
47
|
-
@exec_helper.execute "sudo chmod 666 #{@deliverables[:metadata][:descriptor]}"
|
48
|
-
|
49
|
-
customize( @deliverables[:disk] ) do |guestfs, guestfs_helper|
|
50
|
-
# TODO is this really needed?
|
51
|
-
@log.debug "Uploading '/etc/resolv.conf'..."
|
52
|
-
guestfs.upload( "/etc/resolv.conf", "/etc/resolv.conf" )
|
53
|
-
@log.debug "'/etc/resolv.conf' uploaded."
|
54
|
-
|
55
|
-
change_configuration( guestfs )
|
56
|
-
|
57
|
-
@log.info "Executing post operations after build..."
|
58
|
-
|
59
|
-
unless @appliance_config.post['base'].nil?
|
60
|
-
@appliance_config.post['base'].each do |cmd|
|
61
|
-
@log.debug "Executing #{cmd}"
|
62
|
-
guestfs.sh( cmd )
|
63
|
-
end
|
64
|
-
@log.debug "Post commands from appliance definition file executed."
|
65
|
-
else
|
66
|
-
@log.debug "No commands specified, skipping."
|
67
|
-
end
|
68
|
-
|
69
|
-
change_configuration( guestfs )
|
70
|
-
set_motd( guestfs )
|
71
|
-
install_version_files( guestfs )
|
72
|
-
install_repos( guestfs )
|
73
|
-
|
74
|
-
yield guestfs, guestfs_helper if block_given?
|
75
|
-
|
76
|
-
@log.info "Post operations executed."
|
77
|
-
end
|
78
|
-
|
79
|
-
@log.info "Base image for #{@appliance_config.name} appliance was built successfully."
|
80
|
-
end
|
81
|
-
|
82
|
-
def change_configuration( guestfs )
|
83
|
-
@log.debug "Changing configuration files using augeas..."
|
84
|
-
guestfs.aug_init( "/", 0 )
|
85
|
-
# don't use DNS for SSH
|
86
|
-
guestfs.aug_set( "/files/etc/ssh/sshd_config/UseDNS", "no" ) if guestfs.exists( '/etc/ssh/sshd_config' ) != 0
|
87
|
-
# setting SELinux into permissive mode
|
88
|
-
guestfs.aug_set("/files/etc/sysconfig/selinux/SELINUX", "permissive")
|
89
|
-
guestfs.aug_save
|
90
|
-
@log.debug "Augeas changes saved."
|
91
|
-
end
|
92
|
-
|
93
|
-
def install_version_files( guestfs )
|
94
|
-
@log.debug "Installing BoxGrinder version files..."
|
95
|
-
guestfs.sh( "echo 'BOXGRINDER_VERSION=#{@config.version_with_release}' > /etc/sysconfig/boxgrinder" )
|
96
|
-
guestfs.sh( "echo 'APPLIANCE_NAME=#{@appliance_config.name}' >> /etc/sysconfig/boxgrinder" )
|
97
|
-
@log.debug "Version files installed."
|
98
|
-
end
|
99
|
-
|
100
|
-
def set_motd( guestfs )
|
101
|
-
@log.debug "Setting up '/etc/motd'..."
|
102
|
-
# set nice banner for SSH
|
103
|
-
motd_file = "/etc/init.d/motd"
|
104
|
-
guestfs.upload( "#{File.dirname( __FILE__ )}/src/motd.init", motd_file )
|
105
|
-
guestfs.sh( "sed -i s/#VERSION#/'#{@appliance_config.version}.#{@appliance_config.release}'/ #{motd_file}" )
|
106
|
-
guestfs.sh( "sed -i s/#APPLIANCE#/'#{@appliance_config.name} appliance'/ #{motd_file}" )
|
107
|
-
|
108
|
-
guestfs.sh( "/bin/chmod +x #{motd_file}" )
|
109
|
-
guestfs.sh( "/sbin/chkconfig --add motd" )
|
110
|
-
@log.debug "'/etc/motd' is nice now."
|
111
|
-
end
|
112
|
-
|
113
|
-
def install_repos( guestfs )
|
114
|
-
@log.debug "Installing repositories from appliance definition file..."
|
115
|
-
@appliance_config.repos.each do |repo|
|
116
|
-
if repo['ephemeral']
|
117
|
-
@log.debug "Repository '#{repo['name']}' is an ephemeral repo. It'll not be installed in the appliance."
|
118
|
-
next
|
119
|
-
end
|
120
|
-
|
121
|
-
@log.debug "Installing #{repo['name']} repo..."
|
122
|
-
repo_file = File.read( "#{File.dirname( __FILE__ )}/src/base.repo").gsub( /#NAME#/, repo['name'] )
|
123
|
-
|
124
|
-
['baseurl', 'mirrorlist'].each do |type|
|
125
|
-
repo_file << ("#{type}=#{repo[type]}\n") unless repo[type].nil?
|
126
|
-
end
|
127
|
-
|
128
|
-
guestfs.write_file( "/etc/yum.repos.d/#{repo['name']}.repo", repo_file, 0 )
|
129
|
-
end
|
130
|
-
@log.debug "Repositories installed."
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
end
|