boxgrinder-build 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|