boxgrinder-build 0.2.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/bin/boxgrinder-build +81 -0
  2. data/docs/examples/appliances/appliances.appl +5 -0
  3. data/docs/examples/appliances/minimal.appl +9 -0
  4. data/docs/examples/appliances/mix.appl +8 -0
  5. data/docs/examples/appliances/packages.appl +13 -0
  6. data/lib/boxgrinder-build/appliance.rb +85 -18
  7. data/lib/boxgrinder-build/helpers/appliance-customize-helper.rb +2 -2
  8. data/lib/boxgrinder-build/helpers/guestfs-helper.rb +18 -15
  9. data/lib/boxgrinder-build/helpers/package-helper.rb +65 -0
  10. data/lib/boxgrinder-build/helpers/plugin-helper.rb +89 -0
  11. data/lib/boxgrinder-build/{defaults.rb → managers/base-plugin-manager.rb} +41 -8
  12. data/lib/{boxgrinder-build.rb → boxgrinder-build/managers/delivery-plugin-manager.rb} +15 -18
  13. data/lib/boxgrinder-build/managers/operating-system-plugin-manager.rb +6 -0
  14. data/{bin/boxgrinder → lib/boxgrinder-build/managers/platform-plugin-manager.rb} +6 -3
  15. data/lib/boxgrinder-build/plugins/base-plugin.rb +98 -0
  16. data/lib/boxgrinder-build/plugins/delivery/base/base-delivery-plugin.rb +43 -0
  17. data/lib/boxgrinder-build/plugins/delivery/local/local-plugin.rb +57 -0
  18. data/lib/boxgrinder-build/{helpers → plugins/delivery/s3}/aws-helper.rb +0 -0
  19. data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +133 -0
  20. data/lib/boxgrinder-build/{helpers/ssh-helper.rb → plugins/delivery/sftp/sftp-plugin.rb} +61 -42
  21. data/lib/boxgrinder-build/{appliance-kickstart.rb → plugins/os/base/kickstart.rb} +45 -55
  22. data/lib/boxgrinder-build/{images/raw-image.rb → plugins/os/base/rpm-based-os-plugin.rb} +63 -60
  23. data/lib/boxgrinder-build/{erb → plugins/os/base/src}/appliance.ks.erb +2 -5
  24. data/{src → lib/boxgrinder-build/plugins/os/base/src}/base.repo +0 -0
  25. data/{src → lib/boxgrinder-build/plugins/os/base/src}/motd.init +0 -0
  26. data/lib/boxgrinder-build/{validators/appliance-dependency-validator.rb → plugins/os/base/validators/rpm-dependency-validator.rb} +1 -1
  27. data/lib/boxgrinder-build/{models/ssh-config.rb → plugins/os/base-operating-system-plugin.rb} +10 -17
  28. data/lib/boxgrinder-build/plugins/os/centos/centos-plugin.rb +72 -0
  29. data/lib/boxgrinder-build/plugins/os/fedora/fedora-plugin.rb +66 -0
  30. data/lib/boxgrinder-build/plugins/os/rhel/rhel-plugin.rb +38 -0
  31. data/lib/boxgrinder-build/plugins/platform/base-platform-plugin.rb +37 -0
  32. data/lib/boxgrinder-build/plugins/platform/ec2/ec2-plugin.rb +283 -0
  33. data/{src → lib/boxgrinder-build/plugins/platform/ec2/src}/f12/yum.conf +0 -0
  34. data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/f12-i386-boxgrinder.repo +0 -0
  35. data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/f12-x86_64-boxgrinder.repo +0 -0
  36. data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/fstab_32bit +0 -0
  37. data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/fstab_64bit +0 -0
  38. data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/ifcfg-eth0 +0 -0
  39. data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/rc_local +1 -4
  40. data/{src/README.vmware → lib/boxgrinder-build/plugins/platform/vmware/src/README} +10 -10
  41. data/{src → lib/boxgrinder-build/plugins/platform/vmware/src}/base.vmdk +1 -1
  42. data/{src → lib/boxgrinder-build/plugins/platform/vmware/src}/base.vmx +0 -0
  43. data/lib/boxgrinder-build/plugins/platform/vmware/vmware-plugin.rb +181 -0
  44. data/lib/boxgrinder-build/validators/config-validator.rb +0 -19
  45. metadata +73 -44
  46. data/docs/examples/appliances/appliances-appliance/appliances-appliance.appl +0 -6
  47. data/docs/examples/appliances/appliances-appliance/appliances-appliance.pp +0 -16
  48. data/docs/examples/appliances/minimal-appliance/minimal-appliance.appl +0 -2
  49. data/docs/examples/appliances/minimal-appliance/minimal-appliance.pp +0 -16
  50. data/docs/examples/appliances/mix-appliance/mix-appliance.appl +0 -9
  51. data/docs/examples/appliances/mix-appliance/mix-appliance.pp +0 -16
  52. data/docs/examples/appliances/packages-appliance/packages-appliance.appl +0 -6
  53. data/docs/examples/appliances/packages-appliance/packages-appliance.pp +0 -16
  54. data/extras/sign-rpms +0 -12
  55. data/lib/boxgrinder-build/boxgrinder.rb +0 -93
  56. data/lib/boxgrinder-build/helpers/release-helper.rb +0 -136
  57. data/lib/boxgrinder-build/images/ec2-image.rb +0 -317
  58. data/lib/boxgrinder-build/images/vmware-image.rb +0 -214
  59. data/lib/boxgrinder-build/validators/appliance-definition-validator.rb +0 -89
  60. data/lib/progressbar/progressbar.rb +0 -236
  61. data/src/oddthesis/RPM-GPG-KEY-oddthesis +0 -30
  62. data/src/oddthesis/oddthesis.repo +0 -23
@@ -0,0 +1,283 @@
1
+ # JBoss, Home of Professional Open Source
2
+ # Copyright 2009, Red Hat Middleware LLC, and individual contributors
3
+ # by the @authors tag. See the copyright.txt in the distribution for a
4
+ # full listing of individual contributors.
5
+ #
6
+ # This is free software; you can redistribute it and/or modify it
7
+ # under the terms of the GNU Lesser General Public License as
8
+ # published by the Free Software Foundation; either version 2.1 of
9
+ # the License, or (at your option) any later version.
10
+ #
11
+ # This software is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this software; if not, write to the Free
18
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
20
+
21
+ require 'boxgrinder-build/plugins/platform/base-platform-plugin'
22
+
23
+ module BoxGrinder
24
+ class EC2Plugin < BasePlatformPlugin
25
+ def info
26
+ {
27
+ :name => :ec2,
28
+ :full_name => "Amazon Elastic Compute Cloud (Amazon EC2)"
29
+ }
30
+ end
31
+
32
+ SUPPORTED_OSES = {
33
+ 'fedora' => ["11"]
34
+ }
35
+
36
+ REGIONS = {'us_east' => 'url'}
37
+
38
+ KERNELS = {
39
+ 'us_east' => {
40
+ 'fedora' => {
41
+ '11' => {
42
+ 'i386' => {:aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc', :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.i686.rpm'},
43
+ 'x86_64' => {:aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da', :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.x86_64.rpm'}
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ def after_init
50
+ @deliverables[:disk] = "#{@appliance_config.path.dir.build}/ec2/#{@appliance_config.name}.ec2"
51
+
52
+ end
53
+
54
+ def supported_os
55
+ supported = ""
56
+
57
+ SUPPORTED_OSES.each_key do |os_name|
58
+ supported << "#{os_name}, versions: #{SUPPORTED_OSES[os_name].join(", ")}"
59
+ end
60
+
61
+ supported
62
+ end
63
+
64
+ def execute(raw_disk)
65
+ if File.exists?(@deliverables[:disk])
66
+ @log.info "EC2 image for #{@appliance_config.name} appliance already exists, skipping..."
67
+ return
68
+ end
69
+
70
+ unless SUPPORTED_OSES[@appliance_config.os.name].include?(@appliance_config.os.version)
71
+ @log.error "EC2 platform plugin for Linux operating systems supports: #{supported_os}. Your OS is #{@appliance_config.os.name} #{@appliance_config.os.version}."
72
+ return
73
+ end
74
+
75
+ FileUtils.mkdir_p File.dirname(@deliverables[:disk])
76
+
77
+ @log.info "Converting #{@appliance_config.name} appliance image to EC2 format..."
78
+
79
+ begin
80
+ ec2_prepare_disk
81
+ ec2_create_filesystem
82
+ rescue => e
83
+ raise "Error while preparing EC2 disk image. See logs for more info"
84
+ end
85
+
86
+ raw_disk_offset = calculate_disk_offset(raw_disk)
87
+
88
+ ec2_disk_mount_dir = "#{@appliance_config.path.dir.build}/tmp/ec2-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
89
+ raw_disk_mount_dir = "#{@appliance_config.path.dir.build}/tmp/raw-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
90
+
91
+
92
+ begin
93
+ ec2_loop_device = mount_image(@deliverables[:disk], ec2_disk_mount_dir)
94
+ raw_loop_device = mount_image(raw_disk, raw_disk_mount_dir, raw_disk_offset)
95
+ rescue => e
96
+ raise "Error while mounting image. See logs for more info"
97
+ end
98
+
99
+ sync_files(raw_disk_mount_dir, ec2_disk_mount_dir)
100
+
101
+ umount_image(raw_disk, raw_disk_mount_dir, raw_loop_device)
102
+ umount_image(@deliverables[:disk], ec2_disk_mount_dir, ec2_loop_device)
103
+
104
+ customize(@deliverables[:disk]) do |guestfs, guestfs_helper|
105
+ create_devices(guestfs)
106
+ upload_fstab(guestfs)
107
+
108
+ guestfs.mkdir("/data") if @appliance_config.is64bit?
109
+
110
+ enable_networking(guestfs)
111
+ upload_rc_local(guestfs)
112
+
113
+ guestfs_helper.rebuild_rpm_database
114
+
115
+ install_additional_packages(guestfs)
116
+ change_configuration(guestfs)
117
+
118
+ # if @appliance_config.os.name.eql?("fedora") and @appliance_config.os.version.to_s.eql?("12")
119
+ # @log.debug "Downgrading udev package to use in EC2 environment..."
120
+ #
121
+ # repo_included = false
122
+ #
123
+ # @appliance_config.repos.each do |repo|
124
+ # repo_included = true if repo['baseurl'] == "http://repo.boxgrinder.org/boxgrinder/packages/fedora/12/RPMS/#{@appliance_config.hardware.arch}"
125
+ # end
126
+ #
127
+ # guestfs.upload( "#{File.dirname( __FILE__ )}/src/f12-#{@appliance_config.hardware.arch}-boxgrinder.repo", "/etc/yum.repos.d/f12-#{@appliance_config.hardware.arch}-boxgrinder.repo" ) unless repo_included
128
+ # guestfs.sh( "yum -y downgrade udev-142" )
129
+ # guestfs.upload( "#{File.dirname( __FILE__ )}/src/f12/yum.conf", "/etc/yum.conf" )
130
+ # guestfs.rm_rf( "/etc/yum.repos.d/f12-#{@appliance_config.hardware.arch}-boxgrinder.repo" ) unless repo_included
131
+ #
132
+ # @log.debug "Package udev downgraded."
133
+ #
134
+ # # TODO EC2 fix, remove that after Fedora pushes kernels to Amazon
135
+ # @log.debug "Disabling unnecessary services..."
136
+ # guestfs.sh( "/sbin/chkconfig ksm off" ) if guestfs.exists( "/etc/init.d/ksm" ) != 0
137
+ # guestfs.sh( "/sbin/chkconfig ksmtuned off" ) if guestfs.exists( "/etc/init.d/ksmtuned" ) != 0
138
+ # @log.debug "Services disabled."
139
+ # end
140
+ end
141
+
142
+ @log.info "Image converted to EC2 format."
143
+ end
144
+
145
+ def ec2_prepare_disk
146
+ # TODO add progress bar?
147
+ # TODO using whole 10GB is fine?
148
+ @log.debug "Preparing disk for EC2 image..."
149
+ @exec_helper.execute "dd if=/dev/zero of=#{@deliverables[:disk]} bs=1 count=0 seek=#{10 * 1024}M"
150
+ @log.debug "Disk for EC2 image prepared"
151
+ end
152
+
153
+ def ec2_create_filesystem
154
+ @log.debug "Creating filesystem..."
155
+ @exec_helper.execute "mkfs.ext3 -F #{@deliverables[:disk]}"
156
+ @log.debug "Filesystem created"
157
+ end
158
+
159
+ def calculate_disk_offset(disk)
160
+ loop_device = get_loop_device
161
+
162
+ @exec_helper.execute("sudo losetup #{loop_device} #{disk}")
163
+ offset = @exec_helper.execute("sudo parted #{loop_device} 'unit B print' | grep Number -A 1 | tail -n 1 | awk '{ print $2 }'").strip.chop.scan(/^\d+/).to_s
164
+ @exec_helper.execute("sudo losetup -d #{loop_device}")
165
+
166
+ offset
167
+ end
168
+
169
+ def mount_image(disk, mount_dir, offset = 0)
170
+ loop_device = get_loop_device
171
+
172
+ @log.debug "Mounting image #{File.basename(disk)} in #{mount_dir} using #{loop_device} with offset #{offset}"
173
+ FileUtils.mkdir_p(mount_dir)
174
+ @exec_helper.execute("sudo losetup -o #{offset.to_s} #{loop_device} #{disk}")
175
+ @exec_helper.execute("sudo mount #{loop_device} -t ext3 #{ mount_dir}")
176
+
177
+ loop_device
178
+ end
179
+
180
+ def umount_image(disk, mount_dir, loop_device)
181
+ @log.debug "Unmounting image #{File.basename(disk)}"
182
+ @exec_helper.execute("sudo umount -d #{loop_device}")
183
+ FileUtils.rm_rf(mount_dir)
184
+ end
185
+
186
+
187
+ def sync_files(from_dir, to_dir)
188
+ @log.debug "Syncing files between #{from_dir} and #{to_dir}..."
189
+ @exec_helper.execute "sudo rsync -u -r -a #{from_dir}/* #{to_dir}"
190
+ @log.debug "Sync finished."
191
+ end
192
+
193
+ def cache_rpms(rpms)
194
+ for name in rpms.keys
195
+ cache_file = "#{@config.dir.src_cache}/#{name}"
196
+
197
+ if (!File.exist?(cache_file))
198
+ FileUtils.mkdir_p(@config.dir.src_cache)
199
+ @exec_helper.execute("wget #{rpms[name]} -O #{cache_file}")
200
+ end
201
+ end
202
+ end
203
+
204
+ def create_devices(guestfs)
205
+ @log.debug "Creating required devices..."
206
+ guestfs.sh("/sbin/MAKEDEV -d /dev -x console")
207
+ guestfs.sh("/sbin/MAKEDEV -d /dev -x null")
208
+ guestfs.sh("/sbin/MAKEDEV -d /dev -x zero")
209
+ @log.debug "Devices created."
210
+ end
211
+
212
+ def upload_fstab(guestfs)
213
+ @log.debug "Uploading '/etc/fstab' file..."
214
+ fstab_file = @appliance_config.is64bit? ? "#{File.dirname(__FILE__)}/src/fstab_64bit" : "#{File.dirname(__FILE__)}/src/fstab_32bit"
215
+ guestfs.upload(fstab_file, "/etc/fstab")
216
+ @log.debug "'/etc/fstab' file uploaded."
217
+ end
218
+
219
+ # enable networking on default runlevels
220
+ def enable_networking(guestfs)
221
+ @log.debug "Enabling networking..."
222
+ guestfs.sh("/sbin/chkconfig network on")
223
+ guestfs.upload("#{File.dirname(__FILE__)}/src/ifcfg-eth0", "/etc/sysconfig/network-scripts/ifcfg-eth0")
224
+ @log.debug "Networking enabled."
225
+ end
226
+
227
+ def upload_rc_local(guestfs)
228
+ @log.debug "Uploading '/etc/rc.local' file..."
229
+ rc_local = Tempfile.new('rc_local')
230
+ rc_local << guestfs.read_file("/etc/rc.local") + File.read("#{File.dirname(__FILE__)}/src/rc_local")
231
+ rc_local.flush
232
+
233
+ guestfs.upload(rc_local.path, "/etc/rc.local")
234
+
235
+ rc_local.close
236
+ @log.debug "'/etc/rc.local' file uploaded."
237
+ end
238
+
239
+ def install_additional_packages(guestfs)
240
+ rpms = {
241
+ "ec2-ami-tools.noarch.rpm" => "http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm"
242
+ }
243
+
244
+ kernel_rpm = KERNELS['us_east'][@appliance_config.os.name][@appliance_config.os.version][@appliance_config.hardware.arch][:rpm]
245
+ rpms[File.basename(kernel_rpm)] = kernel_rpm unless kernel_rpm.nil?
246
+
247
+ cache_rpms(rpms)
248
+
249
+ @log.debug "Installing additional packages (#{rpms.keys.join(", ")})..."
250
+ guestfs.mkdir_p("/tmp/rpms")
251
+
252
+ for name in rpms.keys
253
+ cache_file = "#{@config.dir.src_cache}/#{name}"
254
+ guestfs.upload(cache_file, "/tmp/rpms/#{name}")
255
+ end
256
+
257
+ guestfs.sh("rpm -Uvh --nodeps /tmp/rpms/*.rpm")
258
+ guestfs.rm_rf("/tmp/rpms")
259
+ @log.debug "Additional packages installed."
260
+ end
261
+
262
+ def change_configuration(guestfs)
263
+ @log.debug "Changing configuration files using augeas..."
264
+ guestfs.aug_init("/", 0)
265
+ # disable password authentication
266
+ guestfs.aug_set("/files/etc/ssh/sshd_config/PasswordAuthentication", "no")
267
+ guestfs.aug_save
268
+ @log.debug "Augeas changes saved."
269
+ end
270
+
271
+ def get_loop_device
272
+ begin
273
+ loop_device = @exec_helper.execute("sudo losetup -f 2>&1").strip
274
+ rescue
275
+ raise "No free loop devices available, please free at least one. See 'losetup -d' command."
276
+ end
277
+
278
+ loop_device
279
+ end
280
+
281
+
282
+ end
283
+ end
@@ -1,6 +1,3 @@
1
-
2
- homes=`find /home/* -maxdepth 0 -type d | tr '\n' ' '`
3
-
4
1
  curl http://169.254.169.254/2009-04-04/meta-data/public-keys/0/openssh-key 2>/dev/null >/tmp/my-key
5
2
 
6
3
  if [ $? -eq 0 ] ; then
@@ -13,7 +10,7 @@ if [ $? -eq 0 ] ; then
13
10
  cat /tmp/my-key >> /root/.ssh/authorized_keys
14
11
  chmod 600 /root/.ssh/authorized_keys
15
12
 
16
- for home in $homes; do
13
+ for home in `find /home/* -maxdepth 0 -type d 2>/dev/null | tr '\n' ' '`; do
17
14
  user=`echo $home | awk -F '/' '{ print $3 }'`
18
15
 
19
16
  if [ ! -d $home/.ssh ] ; then
@@ -8,15 +8,15 @@ VMware Personal (VMware Fusion, VMware Server, VMware Player)
8
8
  Required files:
9
9
  ---------------
10
10
 
11
- #APPLIANCE_NAME#-sda.raw
12
- personal/#APPLIANCE_NAME#.vmx
13
- personal/#APPLIANCE_NAME#.vmdk
11
+ #APPLIANCE_NAME#.raw
12
+ #APPLIANCE_NAME#-personal.vmx
13
+ #APPLIANCE_NAME#-personal.vmdk
14
14
 
15
15
  Required steps:
16
16
  ---------------
17
17
 
18
- 1. Extract #APPLIANCE_NAME#-sda.raw file and all files from personal/ directory into one directory.
19
- 2. Add #APPLIANCE_NAME#.vmx to inventory.
18
+ 1. Extract required files into one directory.
19
+ 2. Add #APPLIANCE_NAME#-personal.vmx to inventory.
20
20
  3. Run appliance.
21
21
 
22
22
  VMware Enterprise (VMware ESX/ESXi/, VMware vSphere)
@@ -25,14 +25,14 @@ VMware Enterprise (VMware ESX/ESXi/, VMware vSphere)
25
25
  Required files:
26
26
  ---------------
27
27
 
28
- #APPLIANCE_NAME#-sda.raw
29
- enterprise/#APPLIANCE_NAME#.vmx
30
- enterprise/#APPLIANCE_NAME#.vmdk
28
+ #APPLIANCE_NAME#.raw
29
+ #APPLIANCE_NAME#-enterprise.vmx
30
+ #APPLIANCE_NAME#-enterprise.vmdk
31
31
 
32
32
  Required steps:
33
33
  ---------------
34
34
 
35
- 1. Extract #APPLIANCE_NAME#-sda.raw file and all files from enterprise/ directory into one directory.
35
+ 1. Extract required files into one directory.
36
36
  2. Upload all files to ESX server using vSpehere/VI client.
37
- 3. Add #APPLIANCE_NAME#.vmx to inventory.
37
+ 3. Add #APPLIANCE_NAME#-enterprise.vmx to inventory.
38
38
  4. Run appliance.
@@ -5,7 +5,7 @@ parentCID=ffffffff
5
5
  createType="#TYPE#"
6
6
 
7
7
  # Extent description
8
- RW #TOTAL_SECTORS# #EXTENT_TYPE# "#NAME#-sda.raw" #NUMBER#
8
+ RW #TOTAL_SECTORS# #EXTENT_TYPE# "#NAME#.raw" #NUMBER#
9
9
 
10
10
  # The Disk Data Base
11
11
  #DDB
@@ -0,0 +1,181 @@
1
+ # JBoss, Home of Professional Open Source
2
+ # Copyright 2009, Red Hat Middleware LLC, and individual contributors
3
+ # by the @authors tag. See the copyright.txt in the distribution for a
4
+ # full listing of individual contributors.
5
+ #
6
+ # This is free software; you can redistribute it and/or modify it
7
+ # under the terms of the GNU Lesser General Public License as
8
+ # published by the Free Software Foundation; either version 2.1 of
9
+ # the License, or (at your option) any later version.
10
+ #
11
+ # This software is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this software; if not, write to the Free
18
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
20
+
21
+ require 'boxgrinder-build/plugins/platform/base-platform-plugin'
22
+ require 'boxgrinder-build/helpers/appliance-customize-helper'
23
+
24
+ module BoxGrinder
25
+ class VMwarePlugin < BasePlatformPlugin
26
+ def info
27
+ {
28
+ :name => :vmware,
29
+ :full_name => "VMware"
30
+ }
31
+ end
32
+
33
+ def after_init
34
+ @deliverables[:disk] = "#{@appliance_config.path.dir.build}/vmware/#{@appliance_config.name}.raw"
35
+
36
+ @deliverables[:metadata] = {
37
+ :vmx_enterprise => "#{@appliance_config.path.dir.build}/vmware/#{@appliance_config.name}-enterprise.vmx",
38
+ :vmdk_enterprise => "#{@appliance_config.path.dir.build}/vmware/#{@appliance_config.name}-enterprise.vmdk",
39
+ :vmx_personal => "#{@appliance_config.path.dir.build}/vmware/#{@appliance_config.name}-personal.vmx",
40
+ :vmdk_personal => "#{@appliance_config.path.dir.build}/vmware/#{@appliance_config.name}-personal.vmdk"
41
+ }
42
+
43
+ @deliverables[:other] = {
44
+ :readme => "#{@appliance_config.path.dir.build}/vmware/README"
45
+ }
46
+ end
47
+
48
+
49
+ def execute( base_image_path )
50
+ @log.info "Converting image to VMware format..."
51
+ @log.debug "Copying VMware image file, this may take several minutes..."
52
+
53
+ FileUtils.mkdir_p File.dirname( @deliverables[:disk] )
54
+
55
+ @exec_helper.execute "cp #{base_image_path} #{@deliverables[:disk]}" if ( !File.exists?( @deliverables[:disk] ) || File.new( base_image_path ).mtime > File.new( @deliverables[:disk] ).mtime )
56
+
57
+ @log.debug "VMware image copied."
58
+
59
+ if @appliance_config.post.vmware.size > 0
60
+ customize( @deliverables[:disk] ) do |guestfs, guestfs_helper|
61
+ @appliance_config.post.vmware.each do |cmd|
62
+ @log.debug "Executing #{cmd}"
63
+ guestfs.sh( cmd )
64
+ end
65
+ @log.debug "Post commands from appliance definition file executed."
66
+ end
67
+ else
68
+ @log.debug "No commands specified, skipping."
69
+ end
70
+
71
+ build_vmware_enterprise
72
+ build_vmware_personal
73
+
74
+ readme = File.open( "#{File.dirname(__FILE__)}/src/README" ).read
75
+ readme.gsub!( /#APPLIANCE_NAME#/, @appliance_config.name )
76
+ readme.gsub!( /#NAME#/, @config.name )
77
+ readme.gsub!( /#VERSION#/, @config.version_with_release )
78
+
79
+ File.open( @deliverables[:other][:readme], "w") {|f| f.write( readme ) }
80
+
81
+ @log.info "Image converted to VMware format."
82
+ end
83
+
84
+ # returns value of cylinders, heads and sector for selected disk size (in GB)
85
+
86
+ def generate_scsi_chs(disk_size)
87
+ disk_size = (disk_size * 1024).to_i
88
+
89
+ gb_sectors = 2097152
90
+
91
+ if disk_size <= 1024
92
+ h = 128
93
+ s = 32
94
+ else
95
+ h = 255
96
+ s = 63
97
+ end
98
+
99
+ c = disk_size / 1024 * gb_sectors / (h*s)
100
+ total_sectors = gb_sectors * disk_size / 1024
101
+
102
+ return [ c, h, s, total_sectors ]
103
+ end
104
+
105
+ def change_vmdk_values( type )
106
+ vmdk_data = File.open( "#{File.dirname( __FILE__ )}/src/base.vmdk" ).read
107
+
108
+ disk_size = 0.0
109
+ @appliance_config.hardware.partitions.values.each { |part| disk_size += part['size'].to_f }
110
+
111
+ c, h, s, total_sectors = generate_scsi_chs( disk_size )
112
+
113
+ is_enterprise = type.eql?("vmfs")
114
+
115
+ vmdk_data.gsub!( /#NAME#/, @appliance_config.name )
116
+ vmdk_data.gsub!( /#TYPE#/, type )
117
+ vmdk_data.gsub!( /#EXTENT_TYPE#/, is_enterprise ? "VMFS" : "FLAT" )
118
+ vmdk_data.gsub!( /#NUMBER#/, is_enterprise ? "" : "0" )
119
+ vmdk_data.gsub!( /#HW_VERSION#/, is_enterprise ? "4" : "3" )
120
+ vmdk_data.gsub!( /#CYLINDERS#/, c.to_s )
121
+ vmdk_data.gsub!( /#HEADS#/, h.to_s )
122
+ vmdk_data.gsub!( /#SECTORS#/, s.to_s )
123
+ vmdk_data.gsub!( /#TOTAL_SECTORS#/, total_sectors.to_s )
124
+
125
+ vmdk_data
126
+ end
127
+
128
+ def change_common_vmx_values
129
+ vmx_data = File.open( "#{File.dirname( __FILE__ )}/src/base.vmx" ).read
130
+
131
+ # replace version with current appliance version
132
+ vmx_data.gsub!( /#VERSION#/, "#{@appliance_config.version}.#{@appliance_config.release}" )
133
+ # replace builder with current builder name and version
134
+ vmx_data.gsub!( /#BUILDER#/, "#{@config.name} #{@config.version_with_release}" )
135
+ # change name
136
+ vmx_data.gsub!( /#NAME#/, @appliance_config.name.to_s )
137
+ # and summary
138
+ vmx_data.gsub!( /#SUMMARY#/, @appliance_config.summary.to_s )
139
+ # replace guestOS informations to: linux or otherlinux-64, this seems to be the savests values
140
+ vmx_data.gsub!( /#GUESTOS#/, "#{@appliance_config.hardware.arch == "x86_64" ? "otherlinux-64" : "linux"}" )
141
+ # memory size
142
+ vmx_data.gsub!( /#MEM_SIZE#/, @appliance_config.hardware.memory.to_s )
143
+ # memory size
144
+ vmx_data.gsub!( /#VCPU#/, @appliance_config.hardware.cpus.to_s )
145
+ # network name
146
+ # vmx_data.gsub!( /#NETWORK_NAME#/, @image_config.network_name )
147
+
148
+ vmx_data
149
+ end
150
+
151
+ def build_vmware_personal
152
+ @log.debug "Building VMware personal image."
153
+
154
+ # create .vmx file
155
+ File.open( @deliverables[:metadata][:vmx_personal], "w" ) {|f| f.write( change_common_vmx_values ) }
156
+
157
+ # create disk descriptor file
158
+ File.open( @deliverables[:metadata][:vmdk_personal], "w" ) {|f| f.write( change_vmdk_values( "monolithicFlat" ) ) }
159
+
160
+ @log.debug "VMware personal image was built."
161
+ end
162
+
163
+ def build_vmware_enterprise
164
+ @log.debug "Building VMware enterprise image."
165
+
166
+ # defaults for ESXi (maybe for others too)
167
+ @appliance_config.hardware.network = "VM Network" if @appliance_config.hardware.network.eql?( "NAT" )
168
+
169
+ # create .vmx file
170
+ vmx_data = change_common_vmx_values
171
+ vmx_data += "ethernet0.networkName = \"#{@appliance_config.hardware.network}\""
172
+
173
+ File.open( @deliverables[:metadata][:vmx_enterprise], "w" ) {|f| f.write( vmx_data ) }
174
+
175
+ # create disk descriptor file
176
+ File.open( @deliverables[:metadata][:vmdk_enterprise], "w" ) {|f| f.write( change_vmdk_values( "vmfs" ) ) }
177
+
178
+ @log.debug "VMware enterprise image was built."
179
+ end
180
+ end
181
+ end
@@ -29,7 +29,6 @@ module BoxGrinder
29
29
 
30
30
  def validate
31
31
  validate_common
32
- validate_vmware_files
33
32
  validate_appliance_dir
34
33
  end
35
34
 
@@ -45,23 +44,5 @@ module BoxGrinder
45
44
  def validate_appliance_dir
46
45
  raise ValidationError, "Appliances directory '#{@config.dir.appliances}' doesn't exists, please create it: 'mkdir -p #{@config.dir.appliances}'." if !File.exists?(File.dirname( @config.dir.appliances )) && !File.directory?(File.dirname( @config.dir.appliances ))
47
46
  end
48
-
49
- def validate_vmware_files
50
- if File.exists?( "#{@config.dir.src}/base.vmdk" )
51
- @config.files.base_vmdk = "#{@config.dir.src}/base.vmdk"
52
- else
53
- @config.files.base_vmdk = "#{@config.dir.base}/src/base.vmdk"
54
- end
55
-
56
- raise ValidationError, "base.vmdk file doesn't exists, please check you configuration)" unless File.exists?( @config.files.base_vmdk )
57
-
58
- if File.exists?( "#{@config.dir.src}/base.vmx" )
59
- @config.files.base_vmx = "#{@config.dir.src}/base.vmx"
60
- else
61
- @config.files.base_vmx = "#{@config.dir.base}/src/base.vmx"
62
- end
63
-
64
- raise ValidationError, "base.vmx file doesn't exists, please check you configuration)" unless File.exists?( @config.files.base_vmx )
65
- end
66
47
  end
67
48
  end