boxgrinder-build 0.2.0 → 0.3.2

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