boxgrinder-build 0.0.1
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/LICENSE +165 -0
- data/README +4 -0
- data/appliances/jeos.appl +22 -0
- data/appliances/meta.appl +41 -0
- data/bin/boxgrinder +23 -0
- data/docs/examples/appliances/appliances-appliance/appliances-appliance.appl +6 -0
- data/docs/examples/appliances/appliances-appliance/appliances-appliance.pp +16 -0
- data/docs/examples/appliances/minimal-appliance/minimal-appliance.appl +2 -0
- data/docs/examples/appliances/minimal-appliance/minimal-appliance.pp +16 -0
- data/docs/examples/appliances/mix-appliance/mix-appliance.appl +9 -0
- data/docs/examples/appliances/mix-appliance/mix-appliance.pp +16 -0
- data/docs/examples/appliances/packages-appliance/packages-appliance.appl +6 -0
- data/docs/examples/appliances/packages-appliance/packages-appliance.pp +16 -0
- data/docs/node-info/pom.xml +31 -0
- data/docs/node-info/src/main/webapp/META-INF/MANIFEST.MF +3 -0
- data/docs/node-info/src/main/webapp/WEB-INF/web.xml +7 -0
- data/docs/node-info/src/main/webapp/index.jsp +70 -0
- data/extras/sign-rpms +12 -0
- data/lib/boxgrinder-build/appliance-kickstart.rb +159 -0
- data/lib/boxgrinder-build/appliance.rb +52 -0
- data/lib/boxgrinder-build/boxgrinder.rb +92 -0
- data/lib/boxgrinder-build/erb/appliance.ks.erb +44 -0
- data/lib/boxgrinder-build/helpers/appliance-customize-helper.rb +92 -0
- data/lib/boxgrinder-build/helpers/aws-helper.rb +75 -0
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +86 -0
- data/lib/boxgrinder-build/helpers/rake-helper.rb +71 -0
- data/lib/boxgrinder-build/helpers/release-helper.rb +135 -0
- data/lib/boxgrinder-build/helpers/ssh-helper.rb +140 -0
- data/lib/boxgrinder-build/images/ec2-image.rb +301 -0
- data/lib/boxgrinder-build/images/raw-image.rb +137 -0
- data/lib/boxgrinder-build/images/vmware-image.rb +214 -0
- data/lib/boxgrinder-build/models/ssh-config.rb +44 -0
- data/lib/boxgrinder-build/validators/appliance-config-parameter-validator.rb +37 -0
- data/lib/boxgrinder-build/validators/appliance-definition-validator.rb +89 -0
- data/lib/boxgrinder-build/validators/appliance-dependency-validator.rb +163 -0
- data/lib/boxgrinder-build/validators/appliance-validator.rb +84 -0
- data/lib/boxgrinder-build/validators/aws-validator.rb +58 -0
- data/lib/boxgrinder-build/validators/config-validator.rb +67 -0
- data/lib/boxgrinder-build/validators/ssh-validator.rb +35 -0
- data/lib/boxgrinder-build/validators/validator.rb +91 -0
- data/lib/boxgrinder-build.rb +48 -0
- data/lib/progressbar/progressbar.rb +236 -0
- data/src/README.vmware +38 -0
- data/src/base.repo +4 -0
- data/src/base.vmdk +19 -0
- data/src/base.vmx +45 -0
- data/src/ec2/fstab_32bit +8 -0
- data/src/ec2/fstab_64bit +8 -0
- data/src/ec2/ifcfg-eth0 +7 -0
- data/src/ec2/rc_local +32 -0
- data/src/f12/yum.conf +24 -0
- data/src/motd.init +21 -0
- data/src/oddthesis/RPM-GPG-KEY-oddthesis +30 -0
- data/src/oddthesis/oddthesis.repo +23 -0
- metadata +197 -0
@@ -0,0 +1,214 @@
|
|
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 'rake/tasklib'
|
22
|
+
require 'rexml/document'
|
23
|
+
require 'boxgrinder-build/helpers/appliance-customize-helper'
|
24
|
+
|
25
|
+
module BoxGrinder
|
26
|
+
|
27
|
+
class VMwareImage < Rake::TaskLib
|
28
|
+
|
29
|
+
def initialize( config, appliance_config, options = {} )
|
30
|
+
@config = config
|
31
|
+
@appliance_config = appliance_config
|
32
|
+
|
33
|
+
@log = options[:log] || Logger.new(STDOUT)
|
34
|
+
@exec_helper = options[:exec_helper] || ExecHelper.new( { :log => @log } )
|
35
|
+
|
36
|
+
define_tasks
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_tasks
|
40
|
+
directory @appliance_config.path.dir.vmware.build
|
41
|
+
directory @appliance_config.path.dir.vmware.personal
|
42
|
+
directory @appliance_config.path.dir.vmware.enterprise
|
43
|
+
|
44
|
+
task "appliance:#{@appliance_config.name}:vmware:personal" => [ @appliance_config.path.file.vmware.disk, @appliance_config.path.dir.vmware.personal ] do
|
45
|
+
build_vmware_personal
|
46
|
+
end
|
47
|
+
|
48
|
+
task "appliance:#{@appliance_config.name}:vmware:enterprise" => [ @appliance_config.path.file.vmware.disk, @appliance_config.path.dir.vmware.enterprise ] do
|
49
|
+
build_vmware_enterprise
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Build #{@appliance_config.name} appliance for VMware"
|
53
|
+
task "appliance:#{@appliance_config.name}:vmware" => [ "appliance:#{@appliance_config.name}:vmware:personal", "appliance:#{@appliance_config.name}:vmware:enterprise" ]
|
54
|
+
|
55
|
+
file @appliance_config.path.file.vmware.disk => [ @appliance_config.path.dir.vmware.build, @appliance_config.path.file.raw.xml ] do
|
56
|
+
convert_to_vmware
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# returns value of cylinders, heads and sector for selected disk size (in GB)
|
61
|
+
|
62
|
+
def generate_scsi_chs(disk_size)
|
63
|
+
disk_size = disk_size * 1024
|
64
|
+
|
65
|
+
gb_sectors = 2097152
|
66
|
+
|
67
|
+
if disk_size == 1024
|
68
|
+
h = 128
|
69
|
+
s = 32
|
70
|
+
else
|
71
|
+
h = 255
|
72
|
+
s = 63
|
73
|
+
end
|
74
|
+
|
75
|
+
c = disk_size / 1024 * gb_sectors / (h*s)
|
76
|
+
total_sectors = gb_sectors * disk_size / 1024
|
77
|
+
|
78
|
+
return [ c, h, s, total_sectors ]
|
79
|
+
end
|
80
|
+
|
81
|
+
def change_vmdk_values( type )
|
82
|
+
vmdk_data = File.open( @config.files.base_vmdk ).read
|
83
|
+
|
84
|
+
disk_size = 0
|
85
|
+
@appliance_config.hardware.partitions.values.each { |part| disk_size += part['size'] }
|
86
|
+
|
87
|
+
c, h, s, total_sectors = generate_scsi_chs( disk_size )
|
88
|
+
|
89
|
+
is_enterprise = type.eql?("vmfs")
|
90
|
+
|
91
|
+
vmdk_data.gsub!( /#NAME#/, @appliance_config.name )
|
92
|
+
vmdk_data.gsub!( /#TYPE#/, type )
|
93
|
+
vmdk_data.gsub!( /#EXTENT_TYPE#/, is_enterprise ? "VMFS" : "FLAT" )
|
94
|
+
vmdk_data.gsub!( /#NUMBER#/, is_enterprise ? "" : "0" )
|
95
|
+
vmdk_data.gsub!( /#HW_VERSION#/, is_enterprise ? "4" : "3" )
|
96
|
+
vmdk_data.gsub!( /#CYLINDERS#/, c.to_s )
|
97
|
+
vmdk_data.gsub!( /#HEADS#/, h.to_s )
|
98
|
+
vmdk_data.gsub!( /#SECTORS#/, s.to_s )
|
99
|
+
vmdk_data.gsub!( /#TOTAL_SECTORS#/, total_sectors.to_s )
|
100
|
+
|
101
|
+
vmdk_data
|
102
|
+
end
|
103
|
+
|
104
|
+
def change_common_vmx_values
|
105
|
+
vmx_data = File.open( @config.files.base_vmx ).read
|
106
|
+
|
107
|
+
# replace version with current appliance version
|
108
|
+
vmx_data.gsub!( /#VERSION#/, "#{@appliance_config.version}.#{@appliance_config.release}" )
|
109
|
+
# replace builder with current builder name and version
|
110
|
+
vmx_data.gsub!( /#BUILDER#/, "#{@config.name} #{@config.version_with_release}" )
|
111
|
+
# change name
|
112
|
+
vmx_data.gsub!( /#NAME#/, @appliance_config.name.to_s )
|
113
|
+
# and summary
|
114
|
+
vmx_data.gsub!( /#SUMMARY#/, @appliance_config.summary.to_s )
|
115
|
+
# replace guestOS informations to: linux or otherlinux-64, this seems to be the savests values
|
116
|
+
vmx_data.gsub!( /#GUESTOS#/, "#{@appliance_config.hardware.arch == "x86_64" ? "otherlinux-64" : "linux"}" )
|
117
|
+
# memory size
|
118
|
+
vmx_data.gsub!( /#MEM_SIZE#/, @appliance_config.hardware.memory.to_s )
|
119
|
+
# memory size
|
120
|
+
vmx_data.gsub!( /#VCPU#/, @appliance_config.hardware.cpus.to_s )
|
121
|
+
# network name
|
122
|
+
# vmx_data.gsub!( /#NETWORK_NAME#/, @appliance_config.network_name )
|
123
|
+
|
124
|
+
vmx_data
|
125
|
+
end
|
126
|
+
|
127
|
+
def create_hardlink_to_disk_image( vmware_raw_file )
|
128
|
+
# Hard link RAW disk to VMware destination folder
|
129
|
+
FileUtils.ln( @appliance_config.path.file.vmware.disk, vmware_raw_file ) if ( !File.exists?( vmware_raw_file ) || File.new( @appliance_config.path.file.raw.disk ).mtime > File.new( vmware_raw_file ).mtime )
|
130
|
+
end
|
131
|
+
|
132
|
+
def build_vmware_personal
|
133
|
+
@log.debug "Building VMware personal image."
|
134
|
+
|
135
|
+
# link disk image
|
136
|
+
create_hardlink_to_disk_image( @appliance_config.path.file.vmware.personal.disk )
|
137
|
+
|
138
|
+
# create .vmx file
|
139
|
+
File.open( @appliance_config.path.file.vmware.personal.vmx, "w" ) {|f| f.write( change_common_vmx_values ) }
|
140
|
+
|
141
|
+
# create disk descriptor file
|
142
|
+
File.open( @appliance_config.path.file.vmware.personal.vmdk, "w" ) {|f| f.write( change_vmdk_values( "monolithicFlat" ) ) }
|
143
|
+
|
144
|
+
@log.debug "VMware personal image was built."
|
145
|
+
end
|
146
|
+
|
147
|
+
def build_vmware_enterprise
|
148
|
+
@log.debug "Building VMware enterprise image."
|
149
|
+
|
150
|
+
# link disk image
|
151
|
+
create_hardlink_to_disk_image( @appliance_config.path.file.vmware.enterprise.disk )
|
152
|
+
|
153
|
+
# defaults for ESXi (maybe for others too)
|
154
|
+
@appliance_config.hardware.network = "VM Network" if @appliance_config.hardware.network.eql?( "NAT" )
|
155
|
+
|
156
|
+
# create .vmx file
|
157
|
+
vmx_data = change_common_vmx_values
|
158
|
+
vmx_data += "ethernet0.networkName = \"#{@appliance_config.hardware.network}\""
|
159
|
+
|
160
|
+
File.open( @appliance_config.path.file.vmware.enterprise.vmx, "w" ) {|f| f.write( vmx_data ) }
|
161
|
+
|
162
|
+
# create disk descriptor file
|
163
|
+
File.open( @appliance_config.path.file.vmware.enterprise.vmdk, "w" ) {|f| f.write( change_vmdk_values( "vmfs" ) ) }
|
164
|
+
|
165
|
+
@log.debug "VMware enterprise image was built."
|
166
|
+
end
|
167
|
+
|
168
|
+
def convert_to_vmware
|
169
|
+
@log.info "Converting image to VMware format..."
|
170
|
+
@log.debug "Copying VMware image file, this may take several minutes..."
|
171
|
+
|
172
|
+
@exec_helper.execute "cp #{@appliance_config.path.file.raw.disk} #{@appliance_config.path.file.vmware.disk}" if ( !File.exists?( @appliance_config.path.file.vmware.disk ) || File.new( @appliance_config.path.file.raw.disk ).mtime > File.new( @appliance_config.path.file.vmware.disk ).mtime )
|
173
|
+
|
174
|
+
@log.debug "VMware image copied."
|
175
|
+
|
176
|
+
customize
|
177
|
+
|
178
|
+
@log.info "Image converted to VMware format."
|
179
|
+
end
|
180
|
+
|
181
|
+
def customize
|
182
|
+
@log.debug "Customizing VMware image..."
|
183
|
+
ApplianceCustomizeHelper.new( @config, @appliance_config, @appliance_config.path.file.vmware.disk ).customize do |customizer, guestfs|
|
184
|
+
# install_vmware_tools( customizer )
|
185
|
+
execute_post_operations( guestfs )
|
186
|
+
end
|
187
|
+
@log.debug "Image customized."
|
188
|
+
end
|
189
|
+
|
190
|
+
def execute_post_operations( guestfs )
|
191
|
+
@log.debug "Executing post commands..."
|
192
|
+
for cmd in @appliance_config.post.vmware
|
193
|
+
@log.debug "Executing #{cmd}"
|
194
|
+
guestfs.sh( cmd )
|
195
|
+
end
|
196
|
+
@log.debug "Post commands executed."
|
197
|
+
end
|
198
|
+
|
199
|
+
def install_vmware_tools( customizer )
|
200
|
+
@log.debug "Installing VMware tools..."
|
201
|
+
|
202
|
+
if @appliance_config.is_os_version_stable?
|
203
|
+
rpmfusion_repo_rpm = [ "http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-rawhide.noarch.rpm", "http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-rawhide.noarch.rpm" ]
|
204
|
+
else
|
205
|
+
rpmfusion_repo_rpm = [ "http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm", "http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm" ]
|
206
|
+
end
|
207
|
+
|
208
|
+
#TODO this takes about 11 minutes, need to find a quicker way to install kmod-open-vm-tools package
|
209
|
+
customizer.install_packages( @appliance_config.path.file.vmware.disk, { :packages => { :yum => [ "kmod-open-vm-tools" ] }, :repos => rpmfusion_repo_rpm } )
|
210
|
+
|
211
|
+
@log.debug "VMware tools installed."
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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-core/validators/errors'
|
22
|
+
require 'yaml'
|
23
|
+
|
24
|
+
module BoxGrinder
|
25
|
+
class SSHConfig
|
26
|
+
def initialize( config )
|
27
|
+
@config = config
|
28
|
+
@cfg = @config.data['ssh']
|
29
|
+
@options = {}
|
30
|
+
|
31
|
+
# defaults
|
32
|
+
@options['sftp_create_path'] = true
|
33
|
+
@options['sftp_overwrite'] = false
|
34
|
+
@options['sftp_default_permissions'] = 0644
|
35
|
+
|
36
|
+
@options['host'] = @config.release.ssh['host']
|
37
|
+
@options['username'] = @config.release.ssh['username']
|
38
|
+
@options['password'] = @config.release.ssh['password']
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_reader :options
|
42
|
+
attr_reader :cfg
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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-core/validators/errors'
|
22
|
+
|
23
|
+
module BoxGrinder
|
24
|
+
class ApplianceConfigParameterValidator
|
25
|
+
def validate
|
26
|
+
raise ValidationError, "'#{ENV['BG_HARDWARE_ARCH']}' is not a valid build architecture. Available architectures: #{SUPPORTED_ARCHES.join(", ")}." if (!ENV['BG_HARDWARE_ARCH'].nil? and !SUPPORTED_ARCHES.include?( ENV['BG_HARDWARE_ARCH']))
|
27
|
+
raise ValidationError, "'#{ENV['BG_OS_NAME']}' is not a valid OS name. Please enter valid name." if !ENV['BG_OS_NAME'].nil? && !SUPPORTED_OSES.keys.include?( ENV['BG_OS_NAME'] )
|
28
|
+
|
29
|
+
os_name = ENV['BG_OS_NAME'].nil? ? APPLIANCE_DEFAULTS[:os][:name] : ENV['BG_OS_NAME']
|
30
|
+
|
31
|
+
raise ValidationError, "'#{ENV['BG_OS_VERSION']}' is not a valid OS version for #{os_name}. Please enter valid version." if !ENV['BG_OS_VERSION'].nil? && !SUPPORTED_OSES[os_name].include?( ENV['BG_OS_VERSION'] )
|
32
|
+
raise ValidationError, "'#{ENV['BG_HARDWARE_DISK_SIZE']}' is not a valid disk size. Please enter valid size in GB." if !ENV['BG_HARDWARE_DISK_SIZE'].nil? && ENV['BG_HARDWARE_DISK_SIZE'].to_i == 0
|
33
|
+
raise ValidationError, "'#{ENV['BG_HARDWARE_MEM_SIZE']}' is not a valid memory size. Please enter valid size in MB." if !ENV['BG_HARDWARE_MEM_SIZE'].nil? && ENV['BG_HARDWARE_MEM_SIZE'].to_i == 0
|
34
|
+
raise ValidationError, "'#{ENV['BG_HARDWARE_CPUS']}' is not a valid virtual cpu amount. Please enter valid amount." if !ENV['BG_HARDWARE_CPUS'].nil? && ENV['BG_HARDWARE_CPUS'].to_i == 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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-core/validators/errors'
|
22
|
+
|
23
|
+
module BoxGrinder
|
24
|
+
class ApplianceDefinitionValidator
|
25
|
+
def initialize( appliance_definition )
|
26
|
+
@appliance_definition = appliance_definition
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate
|
30
|
+
check_for_missing_field( 'name' )
|
31
|
+
|
32
|
+
validate_os
|
33
|
+
validate_hardware
|
34
|
+
validate_repos
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def check_for_missing_field( name )
|
40
|
+
raise ApplianceValidationError, "Missing field: appliance definition file should have field '#{name}'" if @appliance_definition[name].nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_os
|
44
|
+
return if @appliance_definition['os'].nil?
|
45
|
+
|
46
|
+
raise ApplianceValidationError, "Unsupported OS: operating system '#{@appliance_definition['os']['name']}' is not supported. Supported OS types: #{SUPPORTED_OSES.keys.join(", ")}. Please correct your appliance definition file, thanks." if !@appliance_definition['os']['name'].nil? and !SUPPORTED_OSES.keys.include?( @appliance_definition['os']['name'] )
|
47
|
+
|
48
|
+
#unless @appliance_definition['os']['version'].nil?
|
49
|
+
#@appliance_definition['os']['version'] = @appliance_definition['os']['version'].to_s
|
50
|
+
#raise ApplianceValidationError, "Not valid OS version: operating system version '#{@appliance_definition['os']['version']}' is not supported for OS type '#{@appliance_definition['os']['name']}'. Supported OS versions for this OS type are: #{SUPPORTED_OSES[@appliance_definition['os']['name']].join(", ")}. Please correct your definition file '#{@appliance_definition_file}', thanks" if !SUPPORTED_OSES[@appliance_definition['os']['name'].nil? ? APPLIANCE_DEFAULTS[:os][:name] : @appliance_definition['os']['name']].include?( @appliance_definition['os']['version'] )
|
51
|
+
#end
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_hardware
|
55
|
+
return if @appliance_definition['hardware'].nil?
|
56
|
+
|
57
|
+
unless @appliance_definition['hardware']['cpus'].nil?
|
58
|
+
raise ApplianceValidationError, "Not valid CPU amount: '#{@appliance_definition['hardware']['cpus']}' is not allowed here. Please correct your appliance definition file, thanks." if @appliance_definition['hardware']['cpus'] =~ /\d/
|
59
|
+
raise ApplianceValidationError, "Not valid CPU amount: Too many or too less CPU's: '#{@appliance_definition['hardware']['cpus']}'. Please choose from 1-4. Please correct your appliance definition file, thanks." unless @appliance_definition['hardware']['cpus'] >= 1 and @appliance_definition['hardware']['cpus'] <= 4
|
60
|
+
end
|
61
|
+
|
62
|
+
unless @appliance_definition['hardware']['memory'].nil?
|
63
|
+
raise ApplianceValidationError, "Not valid memory amount: '#{@appliance_definition['hardware']['memory']}' is wrong value. Please correct your appliance definition file, thanks." if @appliance_definition['hardware']['memory'] =~ /\d/
|
64
|
+
raise ApplianceValidationError, "Not valid memory amount: '#{@appliance_definition['hardware']['memory']}' is not allowed here. Memory should be a multiplicity of 64. Please correct your appliance definition file, thanks." if (@appliance_definition['hardware']['memory'].to_i % 64 > 0)
|
65
|
+
end
|
66
|
+
|
67
|
+
unless @appliance_definition['hardware']['partitions'].nil?
|
68
|
+
raise ApplianceValidationError, "Not valid partitions format: Please correct your appliance definition file, thanks." unless @appliance_definition['hardware']['partitions'].class.eql?(Array)
|
69
|
+
|
70
|
+
for partition in @appliance_definition['hardware']['partitions']
|
71
|
+
raise ApplianceValidationError, "Not valid partition format: '#{partition}' is wrong value. Please correct your appliance definition file, thanks." unless partition.class.eql?(Hash)
|
72
|
+
raise ApplianceValidationError, "Not valid partition format: Keys 'root' and 'size' should be specified for every partition. Please correct your appliance definition file, thanks." if !partition.keys.include?("root") or !partition.keys.include?("size")
|
73
|
+
raise ApplianceValidationError, "Not valid partition size: '#{partition['size']}' is not a valid value. Please correct your appliance definition file, thanks." if partition['size'] =~ /\d/ or partition['size'].to_i < 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_repos
|
79
|
+
return if @appliance_definition['repos'].nil?
|
80
|
+
raise ApplianceValidationError, "Not valid repos format: Please correct your appliance definition file, thanks." unless @appliance_definition['repos'].class.eql?(Array)
|
81
|
+
|
82
|
+
for repo in @appliance_definition['repos']
|
83
|
+
raise ApplianceValidationError, "Not valid repo format: '#{repo}' is wrong value. Please correct your appliance definition file, thanks." unless repo.class.eql?(Hash)
|
84
|
+
raise ApplianceValidationError, "Not valid repo format: Please specify name for repository. Please correct your appliance definition file, thanks." unless repo.keys.include?('name')
|
85
|
+
raise ApplianceValidationError, "Not valid repo format: There is no 'mirrorlist' or 'baseurl' specified for '#{repo['name']}' repository. Please correct your appliance definition file, thanks." unless repo.keys.include?('mirrorlist') or repo.keys.include?('baseurl')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,163 @@
|
|
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 'yaml'
|
22
|
+
|
23
|
+
module BoxGrinder
|
24
|
+
class Repo
|
25
|
+
def initialize( name, baseurl = nil, mirrorlist = nil )
|
26
|
+
@name = name
|
27
|
+
@baseurl = baseurl
|
28
|
+
@mirrorlist = mirrorlist
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :name
|
32
|
+
attr_reader :baseurl
|
33
|
+
attr_reader :mirrorlist
|
34
|
+
end
|
35
|
+
|
36
|
+
class ApplianceDependencyValidator
|
37
|
+
def initialize( config, appliance_config, options = {} )
|
38
|
+
@config = config
|
39
|
+
@appliance_config = appliance_config
|
40
|
+
|
41
|
+
@log = options[:log] || Logger.new(STDOUT)
|
42
|
+
@exec_helper = options[:exec_helper] || ExecHelper.new( { :log => @log } )
|
43
|
+
|
44
|
+
# Because we're using repoquery command from our building environment, we must ensure, that our repository
|
45
|
+
# names are unique
|
46
|
+
@magic_hash = "#{@config.name.downcase.gsub(" ", "_")}-"
|
47
|
+
|
48
|
+
define_tasks
|
49
|
+
end
|
50
|
+
|
51
|
+
def define_tasks
|
52
|
+
desc "Validate packages dependencies for #{@appliance_config.simple_name} appliance"
|
53
|
+
task "appliance:#{@appliance_config.name}:validate:dependencies" => [ @appliance_config.path.file.raw.kickstart ] do
|
54
|
+
# if RAW file is already built, don't check for dependencies
|
55
|
+
resolve_packages unless File.exists?( @appliance_config.path.file.raw.disk )
|
56
|
+
end
|
57
|
+
|
58
|
+
task "appliance:all:validate:dependencies" => [ "appliance:#{@appliance_config.name}:validate:dependencies" ]
|
59
|
+
end
|
60
|
+
|
61
|
+
def resolve_packages
|
62
|
+
@log.info "Resolving packages added to #{@appliance_config.simple_name} appliance definition file..."
|
63
|
+
|
64
|
+
repos = read_repos_from_kickstart_file
|
65
|
+
package_list = generate_package_list
|
66
|
+
repo_list = generate_repo_list( repos )
|
67
|
+
|
68
|
+
generate_yum_config( repos )
|
69
|
+
|
70
|
+
invalid_names = invalid_names( repo_list, package_list )
|
71
|
+
|
72
|
+
if invalid_names.size == 0
|
73
|
+
@log.info "All additional packages for #{@appliance_config.simple_name} appliance successfully resolved."
|
74
|
+
else
|
75
|
+
puts invalid_names.to_yaml
|
76
|
+
raise "Package#{invalid_names.size > 1 ? "s" : ""} #{invalid_names.join(', ')} for #{@appliance_config.simple_name} appliance not found in repositories. Please check package names in appliance definition file."
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def invalid_names( repo_list, package_list )
|
81
|
+
@log.debug "Querying package database..."
|
82
|
+
|
83
|
+
unless @appliance_config.is64bit?
|
84
|
+
arches = "i386,i486,i586,i686"
|
85
|
+
else
|
86
|
+
arches = "x86_64"
|
87
|
+
end
|
88
|
+
|
89
|
+
repoquery_output = @exec_helper.execute( "sudo repoquery --quiet --disablerepo=* --enablerepo=#{repo_list} -c #{@appliance_config.path.file.raw.yum} list available #{package_list.join( ' ' )} --nevra --archlist=#{arches},noarch" )
|
90
|
+
invalid_names = []
|
91
|
+
|
92
|
+
for name in package_list
|
93
|
+
found = false
|
94
|
+
|
95
|
+
repoquery_output.each do |line|
|
96
|
+
line = line.strip
|
97
|
+
|
98
|
+
package = line.match( /^([\S]+)-\d+:/ )
|
99
|
+
package = package.nil? ? line : package[1]
|
100
|
+
|
101
|
+
if package.size > 0 and name.match( /^#{package.gsub(/[\+]/, '\\+')}/ )
|
102
|
+
found = true
|
103
|
+
end
|
104
|
+
end
|
105
|
+
invalid_names += [ name ] unless found
|
106
|
+
end
|
107
|
+
|
108
|
+
invalid_names
|
109
|
+
end
|
110
|
+
|
111
|
+
def generate_package_list
|
112
|
+
packages = []
|
113
|
+
for package in @appliance_config.packages
|
114
|
+
packages << package unless package.match /^@/
|
115
|
+
end
|
116
|
+
packages
|
117
|
+
end
|
118
|
+
|
119
|
+
def generate_repo_list(repos)
|
120
|
+
repo_list = ""
|
121
|
+
|
122
|
+
repos.each do |repo|
|
123
|
+
repo_list += "#{@magic_hash}#{repo.name},"
|
124
|
+
end
|
125
|
+
|
126
|
+
repo_list = repo_list[0, repo_list.length - 1]
|
127
|
+
end
|
128
|
+
|
129
|
+
def read_repos_from_kickstart_file
|
130
|
+
repos = `grep -e "^repo" #{@appliance_config.path.file.raw.kickstart}`
|
131
|
+
repo_list = []
|
132
|
+
|
133
|
+
repos.each do |repo_line|
|
134
|
+
name = repo_line.match( /--name=([\w\-]+)/ )[1]
|
135
|
+
baseurl = repo_line.match( /--baseurl=([\w\-\:\/\.&\?=]+)/ )
|
136
|
+
mirrorlist = repo_line.match( /--mirrorlist=([\w\-\:\/\.&\?=]+)/ )
|
137
|
+
|
138
|
+
baseurl = baseurl[1] unless baseurl.nil?
|
139
|
+
mirrorlist = mirrorlist[1] unless mirrorlist.nil?
|
140
|
+
|
141
|
+
repo_list.push( Repo.new( name, baseurl, mirrorlist ) )
|
142
|
+
end
|
143
|
+
|
144
|
+
repo_list
|
145
|
+
end
|
146
|
+
|
147
|
+
def generate_yum_config( repo_list )
|
148
|
+
File.open( @appliance_config.path.file.raw.yum, "w") do |f|
|
149
|
+
|
150
|
+
f.puts( "[main]\r\ncachedir=/tmp/#{@magic_hash}#{@appliance_config.hardware.arch}-yum-cache/\r\n\r\n" )
|
151
|
+
|
152
|
+
for repo in repo_list
|
153
|
+
f.puts( "[#{@magic_hash}#{repo.name}]" )
|
154
|
+
f.puts( "name=#{repo.name}" )
|
155
|
+
f.puts( "baseurl=#{repo.baseurl}" ) unless repo.baseurl.nil?
|
156
|
+
f.puts( "mirrorlist=#{repo.mirrorlist}" ) unless repo.mirrorlist.nil?
|
157
|
+
f.puts( "enabled=1" )
|
158
|
+
f.puts
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,84 @@
|
|
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-core/validators/errors'
|
22
|
+
require 'yaml'
|
23
|
+
|
24
|
+
module BoxGrinder
|
25
|
+
class ApplianceValidator
|
26
|
+
def initialize( dir_appliances, appliance_def, options = {} )
|
27
|
+
@dir_appliances = dir_appliances
|
28
|
+
|
29
|
+
@log = options[:log] || Logger.new(STDOUT)
|
30
|
+
@exec_helper = options[:exec_helper] || ExecHelper.new( { :log => @log } )
|
31
|
+
|
32
|
+
#check if appliance_def is nil
|
33
|
+
raise ApplianceValidationError, "Appliance definition file must be specified" if appliance_def.nil? or appliance_def.length == 0
|
34
|
+
|
35
|
+
@appliance_name = File.basename( appliance_def, '.appl' )
|
36
|
+
|
37
|
+
# check if file exists
|
38
|
+
raise ApplianceValidationError, "Appliance definition file for '#{@appliance_name}' doesn't exists" unless File.exists?( appliance_def )
|
39
|
+
|
40
|
+
@appliance_def = appliance_def
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate
|
44
|
+
@definition = YAML.load_file( @appliance_def )
|
45
|
+
# check for summary
|
46
|
+
raise ApplianceValidationError, "Appliance definition file for '#{@appliance_name}' should have summary" if @definition['summary'].nil? or @definition['summary'].length == 0
|
47
|
+
# check if selected desktop type is supported
|
48
|
+
raise ApplianceValidationError, "Selected desktop type ('#{@definition['desktop']}') isn't supported. Supported desktop types: #{SUPPORTED_DESKTOP_TYPES.join( "," )}" if !@definition['desktop'].nil? and !SUPPORTED_DESKTOP_TYPES.include?( @definition['desktop'] )
|
49
|
+
# check if all dependent appliances exists
|
50
|
+
#appliances, valid = get_appliances(@appliance_name)
|
51
|
+
#raise ApplianceValidationError, "Could not find all dependent appliances for multiappliance '#{@appliance_name}'" unless valid
|
52
|
+
# check appliance count
|
53
|
+
#raise ApplianceValidationError, "Invalid appliance count for appliance '#{@appliance_name}'" unless appliances.size >= 1
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def get_appliances( appliance_name )
|
59
|
+
appliances = Array.new
|
60
|
+
valid = true
|
61
|
+
|
62
|
+
appliance_def = "#{@dir_appliances}/#{appliance_name}/#{appliance_name}.appl"
|
63
|
+
|
64
|
+
unless File.exists?( appliance_def )
|
65
|
+
@log.info "Appliance configuration file for '#{appliance_name}' doesn't exists, please check your config files."
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
|
69
|
+
appliances_read = YAML.load_file( appliance_def )['appliances']
|
70
|
+
|
71
|
+
appliances_read.each do |appl|
|
72
|
+
appls, v = get_appliances( appl )
|
73
|
+
|
74
|
+
appliances += appls if v
|
75
|
+
valid = false unless v
|
76
|
+
end unless appliances_read.nil? or appliances_read.empty?
|
77
|
+
|
78
|
+
appliances.push( appliance_name )
|
79
|
+
|
80
|
+
[ appliances, valid ]
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|