boxgrinder-build 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/LICENSE +165 -0
  2. data/README +4 -0
  3. data/appliances/jeos.appl +22 -0
  4. data/appliances/meta.appl +41 -0
  5. data/bin/boxgrinder +23 -0
  6. data/docs/examples/appliances/appliances-appliance/appliances-appliance.appl +6 -0
  7. data/docs/examples/appliances/appliances-appliance/appliances-appliance.pp +16 -0
  8. data/docs/examples/appliances/minimal-appliance/minimal-appliance.appl +2 -0
  9. data/docs/examples/appliances/minimal-appliance/minimal-appliance.pp +16 -0
  10. data/docs/examples/appliances/mix-appliance/mix-appliance.appl +9 -0
  11. data/docs/examples/appliances/mix-appliance/mix-appliance.pp +16 -0
  12. data/docs/examples/appliances/packages-appliance/packages-appliance.appl +6 -0
  13. data/docs/examples/appliances/packages-appliance/packages-appliance.pp +16 -0
  14. data/docs/node-info/pom.xml +31 -0
  15. data/docs/node-info/src/main/webapp/META-INF/MANIFEST.MF +3 -0
  16. data/docs/node-info/src/main/webapp/WEB-INF/web.xml +7 -0
  17. data/docs/node-info/src/main/webapp/index.jsp +70 -0
  18. data/extras/sign-rpms +12 -0
  19. data/lib/boxgrinder-build/appliance-kickstart.rb +159 -0
  20. data/lib/boxgrinder-build/appliance.rb +52 -0
  21. data/lib/boxgrinder-build/boxgrinder.rb +92 -0
  22. data/lib/boxgrinder-build/erb/appliance.ks.erb +44 -0
  23. data/lib/boxgrinder-build/helpers/appliance-customize-helper.rb +92 -0
  24. data/lib/boxgrinder-build/helpers/aws-helper.rb +75 -0
  25. data/lib/boxgrinder-build/helpers/guestfs-helper.rb +86 -0
  26. data/lib/boxgrinder-build/helpers/rake-helper.rb +71 -0
  27. data/lib/boxgrinder-build/helpers/release-helper.rb +135 -0
  28. data/lib/boxgrinder-build/helpers/ssh-helper.rb +140 -0
  29. data/lib/boxgrinder-build/images/ec2-image.rb +301 -0
  30. data/lib/boxgrinder-build/images/raw-image.rb +137 -0
  31. data/lib/boxgrinder-build/images/vmware-image.rb +214 -0
  32. data/lib/boxgrinder-build/models/ssh-config.rb +44 -0
  33. data/lib/boxgrinder-build/validators/appliance-config-parameter-validator.rb +37 -0
  34. data/lib/boxgrinder-build/validators/appliance-definition-validator.rb +89 -0
  35. data/lib/boxgrinder-build/validators/appliance-dependency-validator.rb +163 -0
  36. data/lib/boxgrinder-build/validators/appliance-validator.rb +84 -0
  37. data/lib/boxgrinder-build/validators/aws-validator.rb +58 -0
  38. data/lib/boxgrinder-build/validators/config-validator.rb +67 -0
  39. data/lib/boxgrinder-build/validators/ssh-validator.rb +35 -0
  40. data/lib/boxgrinder-build/validators/validator.rb +91 -0
  41. data/lib/boxgrinder-build.rb +48 -0
  42. data/lib/progressbar/progressbar.rb +236 -0
  43. data/src/README.vmware +38 -0
  44. data/src/base.repo +4 -0
  45. data/src/base.vmdk +19 -0
  46. data/src/base.vmx +45 -0
  47. data/src/ec2/fstab_32bit +8 -0
  48. data/src/ec2/fstab_64bit +8 -0
  49. data/src/ec2/ifcfg-eth0 +7 -0
  50. data/src/ec2/rc_local +32 -0
  51. data/src/f12/yum.conf +24 -0
  52. data/src/motd.init +21 -0
  53. data/src/oddthesis/RPM-GPG-KEY-oddthesis +30 -0
  54. data/src/oddthesis/oddthesis.repo +23 -0
  55. 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