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