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.
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