stemcell_builder 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/.gitignore +20 -0
  2. data/.rvmrc +1 -0
  3. data/.travis.yml +1 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +123 -0
  7. data/Rakefile +10 -0
  8. data/assets/box.ovf.erb +81 -0
  9. data/assets/stemcell_mf_schema.yaml +30 -0
  10. data/bin/stemcell_builder +138 -0
  11. data/lib/stemcell.rb +3 -0
  12. data/lib/stemcell/builder.rb +445 -0
  13. data/lib/stemcell/builders/centos.rb +33 -0
  14. data/lib/stemcell/builders/redhat.rb +34 -0
  15. data/lib/stemcell/builders/ubuntu.rb +36 -0
  16. data/lib/stemcell/const.rb +12 -0
  17. data/lib/stemcell/version.rb +10 -0
  18. data/spec/spec_helper.rb +10 -0
  19. data/spec/stemcell_builder/builder_spec.rb +186 -0
  20. data/spec/stemcell_builder/centos_spec.rb +39 -0
  21. data/spec/stemcell_builder/redhat_spec.rb +53 -0
  22. data/spec/stemcell_builder/ubuntu_spec.rb +38 -0
  23. data/stemcell_builder.gemspec +42 -0
  24. data/templates/centos/_60-bosh-sysctl.conf +5 -0
  25. data/templates/centos/_empty_state.yml +9 -0
  26. data/templates/centos/_monitrc +8 -0
  27. data/templates/centos/_ntpdate +10 -0
  28. data/templates/centos/_runonce +46 -0
  29. data/templates/centos/_sysstat +18 -0
  30. data/templates/centos/_variables.sh.erb +31 -0
  31. data/templates/centos/base.sh +23 -0
  32. data/templates/centos/bosh_agent.sh +39 -0
  33. data/templates/centos/cleanup.sh +28 -0
  34. data/templates/centos/definition.rb.erb +37 -0
  35. data/templates/centos/harden.sh +8 -0
  36. data/templates/centos/ks.cfg +43 -0
  37. data/templates/centos/micro.sh +57 -0
  38. data/templates/centos/monit.sh +21 -0
  39. data/templates/centos/postinstall.sh +27 -0
  40. data/templates/centos/ruby.sh +42 -0
  41. data/templates/centos/setup-bosh.sh +20 -0
  42. data/templates/centos/sudo.sh +13 -0
  43. data/templates/centos/timestamp.sh +15 -0
  44. data/templates/centos/vmware-tools.sh +17 -0
  45. data/templates/centos/zerodisk.sh +9 -0
  46. data/templates/noop/erbtest.txt.erb +1 -0
  47. data/templates/noop/test.txt +1 -0
  48. data/templates/redhat/_60-bosh-sysctl.conf +5 -0
  49. data/templates/redhat/_empty_state.yml +9 -0
  50. data/templates/redhat/_monitrc +8 -0
  51. data/templates/redhat/_ntpdate +10 -0
  52. data/templates/redhat/_runonce +46 -0
  53. data/templates/redhat/_sysstat +18 -0
  54. data/templates/redhat/_variables.sh.erb +31 -0
  55. data/templates/redhat/base.sh +41 -0
  56. data/templates/redhat/bosh_agent.sh +37 -0
  57. data/templates/redhat/cleanup.sh +30 -0
  58. data/templates/redhat/definition.rb.erb +38 -0
  59. data/templates/redhat/harden.sh +8 -0
  60. data/templates/redhat/ks.cfg +86 -0
  61. data/templates/redhat/micro.sh +57 -0
  62. data/templates/redhat/monit.sh +21 -0
  63. data/templates/redhat/postinstall.sh +27 -0
  64. data/templates/redhat/rhnreg.sh.erb +15 -0
  65. data/templates/redhat/ruby.sh +42 -0
  66. data/templates/redhat/setup-bosh.sh +20 -0
  67. data/templates/redhat/sudo.sh +13 -0
  68. data/templates/redhat/timestamp.sh +15 -0
  69. data/templates/redhat/vmware-tools.sh +17 -0
  70. data/templates/redhat/zerodisk.sh +9 -0
  71. data/templates/ubuntu/_60-bosh-sysctl.conf +5 -0
  72. data/templates/ubuntu/_empty_state.yml +9 -0
  73. data/templates/ubuntu/_helpers.sh +40 -0
  74. data/templates/ubuntu/_monitrc +8 -0
  75. data/templates/ubuntu/_ntpdate +10 -0
  76. data/templates/ubuntu/_runonce +46 -0
  77. data/templates/ubuntu/_sysstat +18 -0
  78. data/templates/ubuntu/_variables.sh.erb +30 -0
  79. data/templates/ubuntu/apt-upgrade.sh +19 -0
  80. data/templates/ubuntu/base-stemcell.sh +95 -0
  81. data/templates/ubuntu/bosh_agent.sh +39 -0
  82. data/templates/ubuntu/definition.rb.erb +63 -0
  83. data/templates/ubuntu/harden.sh +9 -0
  84. data/templates/ubuntu/micro.sh +57 -0
  85. data/templates/ubuntu/monit.sh +22 -0
  86. data/templates/ubuntu/network-cleanup.sh +17 -0
  87. data/templates/ubuntu/postinstall.sh +45 -0
  88. data/templates/ubuntu/preseed.cfg +87 -0
  89. data/templates/ubuntu/ruby.sh +54 -0
  90. data/templates/ubuntu/setup-bosh.sh +14 -0
  91. data/templates/ubuntu/sudo.sh +14 -0
  92. data/templates/ubuntu/timestamp.sh +13 -0
  93. data/templates/ubuntu/vmware-tools.sh +22 -0
  94. data/templates/ubuntu/zero-disk.sh +10 -0
  95. metadata +375 -0
@@ -0,0 +1,3 @@
1
+ require "stemcell/const"
2
+ require "stemcell/version"
3
+ require "stemcell/builder"
@@ -0,0 +1,445 @@
1
+ require 'logger/colors'
2
+ require 'deep_merge'
3
+ require 'erb'
4
+ require 'securerandom'
5
+ require 'digest/sha1'
6
+ require 'net/scp'
7
+ require 'net/ssh'
8
+ require 'retryable'
9
+ require 'tmpdir'
10
+
11
+ module Bosh::Agent::StemCell
12
+
13
+ # This BaseBuilder abstract class represents the base stemcell builder and should be extended by specific stemcell
14
+ # builders for different distributions
15
+ class BaseBuilder
16
+
17
+ attr_accessor :name, :infrastructure, :architecture
18
+ attr_accessor :agent_src_path, :agent_version, :bosh_protocol
19
+ attr_accessor :prefix, :target
20
+ attr_accessor :iso, :iso_md5, :iso_filename
21
+ attr_accessor :logger
22
+ attr_accessor :vm_name
23
+
24
+ # Stemcell builders are initialized with a manifest and a set of options. The options provided are merged with the
25
+ # defaults to allow the end user/developer to specify only the ones that they wish to change and fallback to the defaults.
26
+ #
27
+ # The stemcell builder options are as follows
28
+ #{
29
+ # :name => 'bosh-stemcell', # Name of the output stemcell
30
+ # :logger => Logger.new(STDOUT), # The logger instance to use
31
+ # :target => "bosh-#@type-#@agent_version.tgz", # Target file to generate, by default it will the ./bosh-#@type-#@agent_version.tgz
32
+ # :infrastructure => 'vsphere', # The target infrastructure, this can be aws||vsphere||openstack
33
+ # :agent_src_path => './bosh_agent-0.7.0.gem', # The path to the stemcell gem to be installed
34
+ # :agent_version => '0.7.0', # Agent version
35
+ # :bosh_protocol => '1', # Bosh protocol version
36
+ # :architecture => 'x86_64', # The target system architecture
37
+ # :prefix => `pwd`, # Directory to use as the staging area and where the stemcell will be generated
38
+ # :iso => nil, # The url from where the builder can download the stemcell
39
+ # :iso_md5 => nil, # The MD5 hash of the iso
40
+ # :iso_filename => nil # Optional iso filename to use/search for in the iso folder
41
+ #}
42
+ #
43
+ # The stemcell manifest is as follows
44
+ #{
45
+ # :name => @name, # the bosh stemcell name given as a part of the options[:name]
46
+ # :version => @agent_version, # The agent version
47
+ # :bosh_protocol => @bosh_protocol,
48
+ # :cloud_properties => {
49
+ # :infrastructure => @infrastructure,
50
+ # :architecture => @architecture
51
+ # :root_device_name => '/dev/sda1'
52
+ # }
53
+ #}
54
+ def initialize(opts)
55
+ initialize_common(opts)
56
+ initialize_micro(opts) if micro?
57
+ sanity_check
58
+ end
59
+
60
+ # This method does the setup, this implementation takes care of copying over the
61
+ # correct definition files, packaging the agent and doing any related setup if needed
62
+ def setup
63
+ copy_definitions
64
+ package_agent
65
+ end
66
+
67
+ def micro?
68
+ !!@micro
69
+ end
70
+
71
+ # This method creates the vm using the #@name as the virtual machine name
72
+ # If an existing VM exists with the same name, it will be deleted.
73
+ def build_vm
74
+ Dir.chdir(@prefix) do
75
+ @logger.info "Building vm #@name"
76
+ nogui_str = gui? ? "" : "--nogui"
77
+
78
+ sh "veewee vbox build '#@vm_name' --force --auto #{nogui_str}", {:on_error => "Unable to build vm #@name"}
79
+
80
+ # execute pre-shutdown hook
81
+ pre_shutdown_hook
82
+
83
+ @logger.info "Export built VM #@name to #@prefix"
84
+ sh "vagrant basebox export '#@vm_name' --force", {:on_error => "Unable to export VM #@name: vagrant basebox export '#@vm_name'"}
85
+ end
86
+
87
+ end
88
+
89
+ def pre_shutdown_hook
90
+ if micro?
91
+ convert_stemcell_to_micro
92
+ end
93
+ end
94
+
95
+ def type
96
+ raise NotImplementedError.new("Type must be initialized")
97
+ end
98
+
99
+ def init_default_iso
100
+ raise NotImplementedError.new("Default ISO options must be provided")
101
+ end
102
+
103
+ # Packages the stemcell contents (defined as the array of file path argument)
104
+ def package_stemcell
105
+ @stemcell_files << generate_image << generate_manifest
106
+ # package up files
107
+ package_files
108
+ end
109
+
110
+ def generate_manifest
111
+ stemcell_mf_path = File.expand_path "stemcell.MF", @prefix
112
+ File.open(stemcell_mf_path, "w") do |f|
113
+ f.write(manifest.to_yaml)
114
+ end
115
+ stemcell_mf_path
116
+ end
117
+
118
+ def generate_image
119
+ image_path = File.join @prefix, "image"
120
+ Dir.chdir(@prefix) do
121
+ sh("tar -xf #@vm_name.box", {:on_error => "Unable to unpack .box file"})
122
+ vmdk_filename = Dir.glob("*.vmdk").first
123
+ Dir.glob("*.ovf") { |ovf_file| fix_virtualbox_ovf(ovf_file, vmdk_filename) } # Fix ovf files
124
+ sh("tar -czf #{image_path} *.vmdk *.ovf", {:on_error=>"Unable to create image file from ovf and vmdk"})
125
+ FileUtils.rm [Dir.glob('*.box'), Dir.glob('*.vmdk'), Dir.glob('*.ovf'), "Vagrantfile"]
126
+ @image_sha1 = Digest::SHA1.file(image_path).hexdigest
127
+ end
128
+ image_path
129
+ end
130
+
131
+ # Main execution method that sets up the directory, builds the VM and packages everything into a stemcell
132
+ def run
133
+ setup
134
+ build_vm
135
+ package_stemcell
136
+ cleanup
137
+ @target
138
+ end
139
+
140
+ def cleanup
141
+ @logger.info "Cleaning up files: #@stemcell_files"
142
+ FileUtils.rm_rf @stemcell_files
143
+ end
144
+
145
+ def manifest
146
+ @manifest ||= {
147
+ "name" => @name,
148
+ "version" => @agent_version,
149
+ "bosh_protocol" => @bosh_protocol,
150
+ "sha1" => @image_sha1,
151
+ "cloud_properties" => {
152
+ "root_device_name" => Bosh::Agent::StemCell::DEFAULT_DEVICE_NAME,
153
+ "infrastructure" => @infrastructure,
154
+ "architecture" => @architecture
155
+ }
156
+ }
157
+ end
158
+
159
+ protected
160
+
161
+ # Cross-platform way of finding an executable in the $PATH.
162
+ #
163
+ # which('ruby') #=> /usr/bin/ruby
164
+ def which(cmd)
165
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
166
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
167
+ exts.each do |ext|
168
+ exe = "#{path}/#{cmd}#{ext}"
169
+ return exe if File.executable? exe
170
+ end
171
+ end
172
+ return nil
173
+ end
174
+
175
+ # Package all files specified as arguments into a tar. The output file is specified by the :target option
176
+ def package_files
177
+ Dir.mktmpdir {|tmpdir|
178
+ @stemcell_files.flatten.each {|file| FileUtils.cp(file, tmpdir) if file && File.exists?(file) } # only copy files that are not nil
179
+ Dir.chdir(tmpdir) do
180
+ @logger.info("Package #@stemcell_files to #@target ...")
181
+ sh "tar -czf #@target *", {:on_error => "unable to package #@stemcell_files into a stemcell"}
182
+ end
183
+ }
184
+ @target
185
+ end
186
+
187
+ def sanity_check
188
+ @logger.info "Sanity check"
189
+
190
+ @logger.info "Checking ssh_port"
191
+ raise "Unable to find port for ssh" if @ssh_port.nil?
192
+
193
+ @logger.info "Checking target file: #@target..."
194
+ if File.exists? @target
195
+ @logger.warn "Target file #@target exists. Moving old file to #@target.bak."
196
+ FileUtils.mv @target, "#@target.bak"
197
+ end
198
+
199
+ @logger.info "Checking agent source: #@agent_src_path"
200
+ raise "Agent source #@agent_src_path doens't exist" unless File.exists? @agent_src_path
201
+
202
+ @logger.info "Checking definitions dir..."
203
+ raise "Definition for '#{type}' does not exist at path '#{definition_dir}'" unless Dir.exist? definition_dir
204
+
205
+ if micro?
206
+ @logger.info "Checking micro stemcell conversion files"
207
+ raise "Micro conversion script does not exist." unless File.exists?(@micro_path)
208
+ raise "Release manifest path missing" unless File.exists?(@release_manifest)
209
+ raise "Release tar path missing" unless File.exists?(@release_tar)
210
+ raise "Package compiler path missing" unless File.exists?(@package_compiler_tar)
211
+ end
212
+
213
+ end
214
+
215
+ # @param [Hash] opts Options: :silent => when set to true, it raises :on_error exception
216
+ # @param [String] cmd Command to execute
217
+ def sh(cmd, opts={})
218
+ unless opts[:on_error]
219
+ opts[:on_error] = "Unable to execute: #{cmd}"
220
+ end
221
+ Kernel.system(cmd)
222
+ exit_status = $?.exitstatus
223
+
224
+ # raise error only if silent is not true and exit_status != 0
225
+ if exit_status != 0
226
+ raise opts[:on_error] unless opts[:silent]
227
+ end
228
+
229
+ exit_status
230
+ end
231
+
232
+ def ssh_options
233
+ {
234
+ :host => '127.0.0.1',
235
+ :user => 'vcap',
236
+ :password => 'c1oudc0w',
237
+ :port => @ssh_port,
238
+ :paranoid => false,
239
+ :timeout => 30
240
+ }
241
+ end
242
+
243
+ def filter_ssh_opts
244
+ opts = ssh_options.dup
245
+ opts.delete(:host) if opts.has_key?(:host)
246
+ opts.delete(:user) if opts.has_key?(:user)
247
+ opts
248
+ end
249
+
250
+ def ssh_execute(cmd)
251
+ @logger.info "Executing #{cmd} on VM [ options: #{filter_ssh_opts} ]"
252
+ Net::SSH.start(ssh_options[:host], ssh_options[:user], filter_ssh_opts) do |ssh|
253
+ ssh.exec! "echo '#{ssh_options[:password]}' | sudo -S /bin/bash '#{cmd}'" do |ch, stream, line|
254
+ @logger.info line
255
+ end
256
+ end
257
+ end
258
+
259
+ def upload_file(source, destination=nil)
260
+ destination ||= "/home/#{ssh_options[:user]}"
261
+
262
+ retryable(:tries => 5, :sleep => 5) do |retries, exception|
263
+ @logger.warn "Failed to upload :#{exception}" unless exception.nil?
264
+ @logger.info "Attempting to upload #{source} to #{destination} [ options: #{filter_ssh_opts} ]"
265
+ Net::SCP.start(ssh_options[:host], ssh_options[:user], filter_ssh_opts) do |scp|
266
+ scp.upload!(source, destination) do|ch, name, sent, total|
267
+ print "\r#{name}: #{(sent.to_f * 100 / total.to_f).to_i}%"
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+ def download_file(source, destination=nil)
274
+ destination ||= File.join(@prefix, File.basename(source))
275
+
276
+ retryable(:tries => 5, :sleep => 5) do |retries, exception|
277
+ @logger.warn "Failed to download :#{exception}" unless exception.nil?
278
+ @logger.info "Attempting to download #{source} to #{destination} [ options: #{filter_ssh_opts} ]"
279
+ Net::SCP.start(ssh_options[:host], ssh_options[:user], filter_ssh_opts) do |scp|
280
+ scp.download!(source, destination) do|ch, name, sent, total|
281
+ print "\r#{name}: #{(sent.to_f * 100 / total.to_f).to_i}%"
282
+ end
283
+ end
284
+ end
285
+ @logger.warn "Unable to download #{source}" unless File.exists?(destination)
286
+ end
287
+
288
+ private
289
+
290
+ def get_free_port
291
+ port = nil
292
+ begin
293
+ socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
294
+ socket.bind(Addrinfo.tcp("127.0.0.1", 0))
295
+ port = socket.local_address.ip_port
296
+ ensure
297
+ socket.close
298
+ end
299
+ port
300
+ end
301
+
302
+ # HACK: This is a compatibility hack for virtualbox-esx compatibility
303
+ def fix_virtualbox_ovf(filepath, vmdk_filename="box-disk1.vmdk")
304
+ @logger.info "Generating ovf file for virtual machine"
305
+ @vmdk_filename = vmdk_filename
306
+ vmware_ovf_erb = File.join(File.dirname(__FILE__), "..", "..", "assets", "box.ovf.erb")
307
+ compile_erb(vmware_ovf_erb, filepath)
308
+ end
309
+
310
+ # Packages the agent into a bosh_agent gem and copies it over to definition_dest_dir
311
+ # so that it can be used as a part of the VM building process by veewee (using the definition).
312
+ def package_agent
313
+ @logger.info "Packaging Bosh Agent to #{definition_dest_dir}/_bosh_agent.tar"
314
+ dst = File.join(definition_dest_dir, "_bosh_agent.tar")
315
+ if File.directory? @agent_src_path
316
+ @logger.info "Tarring up Bosh Agent"
317
+ Dir.chdir(@agent_src_path) do
318
+ sh("tar -cf #{dst} *.gem > /dev/null 2>&1", {:on_error => "Unable to package bosh gems"})
319
+ end
320
+ else
321
+ FileUtils.cp @agent_src_path, dst
322
+ end
323
+ end
324
+
325
+ # Copies the veewee definition directory from ../templates/#@type to #@prefix/definitions/#@name
326
+ def copy_definitions
327
+ @logger.info "Creating definition dest dir"
328
+ if Dir.exists? definition_dest_dir
329
+ @logger.warn "#{definition_dest_dir} already exists, contents will be deleted"
330
+ FileUtils.rm_rf definition_dest_dir
331
+ end
332
+ FileUtils.mkdir_p definition_dest_dir
333
+
334
+ @logger.info "Copying definition from #{definition_dir} to #{definition_dest_dir}"
335
+ FileUtils.cp_r Dir.glob("#{definition_dir}/*"), definition_dest_dir
336
+
337
+ # Compile erb files
338
+ Dir.glob(File.join(definition_dest_dir, '*.erb')) { |erb_file|
339
+ compile_erb(erb_file) # compile erb
340
+ FileUtils.rm erb_file # remove original
341
+ }
342
+ end
343
+
344
+ def definition_dir
345
+ File.expand_path(@definition_dir ||= File.join(File.dirname(__FILE__), "..", "..", "templates", type))
346
+ end
347
+
348
+ def definition_dest_dir
349
+ File.expand_path(@definition_dest_dir ||= File.join(@prefix, "definitions", @vm_name))
350
+ end
351
+
352
+ def compile_erb(erb_file, dst_file=nil)
353
+ new_file_path = dst_file || erb_file.gsub(/\.erb$/,'')
354
+ @logger.debug "Compiling erb #{erb_file} to #{new_file_path}"
355
+
356
+ File.open(new_file_path, "w"){|f|
357
+ f.write(ERB.new(File.read(File.expand_path(erb_file))).result(binding))
358
+ }
359
+ end
360
+
361
+ def gui?
362
+ !!@gui
363
+ end
364
+
365
+ def initialize_common(opts)
366
+ @logger = opts[:logger] || Logger.new(STDOUT)
367
+ @logger.level = Logger.const_get(opts[:log_level] || "INFO")
368
+ @name = opts[:name] || Bosh::Agent::StemCell::DEFAULT_STEMCELL_NAME
369
+ @vm_name = opts[:name] || SecureRandom.uuid.gsub(/-/,'')
370
+ @prefix = File.expand_path(opts[:prefix] || Dir.pwd)
371
+ @infrastructure = opts[:infrastructure] || Bosh::Agent::StemCell::DEFAULT_INFRASTRUCTURE
372
+ @architecture = opts[:architecture] || Bosh::Agent::StemCell::DEFAULT_ARCHITECTURE
373
+ @agent_version = opts[:agent_version] || Bosh::Agent::VERSION
374
+ @bosh_protocol = opts[:agent_protocol] || Bosh::Agent::BOSH_PROTOCOL
375
+ @agent_src_path = File.expand_path(opts[:agent_src_path] || "./bosh_agent-#{@agent_version}.gem")
376
+ @target ||= File.join(@prefix, "#@name-#{type}-#@infrastructure-#{@agent_version}.tgz")
377
+ @iso = opts[:iso]
378
+ @iso_md5 = opts[:iso_md5]
379
+ @gui = opts[:gui]
380
+ @definitions_dir = opts[:definitions_dir]
381
+ @stemcell_files = [] # List of files to be packaged into the stemcell
382
+ @micro = opts[:micro]
383
+ @ssh_port = opts[:ssh_port] || get_free_port()
384
+
385
+ if @iso
386
+ raise "MD5 must be specified is ISO is specified" unless @iso_md5
387
+ @iso_filename ||= File.basename @iso
388
+ else
389
+ init_default_iso
390
+ end
391
+ end
392
+
393
+ def initialize_micro(opts)
394
+ @logger.info "Initializing micro stemcell artifacts"
395
+ #@bosh_src_root = opts[:bosh_src_root] || File.expand_path("bosh", @prefix)
396
+ @release_manifest = opts[:release_manifest] # || default_release_manifest
397
+ @release_tar = opts[:release_tar]
398
+ @package_compiler_tar = opts[:package_compiler]
399
+ @micro_path = opts[:micro_path] || File.join(definition_dir, "micro.sh")
400
+
401
+ # This is kind of a hack :(
402
+ if File.exists?(@package_compiler_tar) && File.directory?(@package_compiler_tar)
403
+ # Tar up the package
404
+ tmpdir = Dir.mktmpdir
405
+ tmp_package_compiler_tar = File.join(tmpdir, "_package_compiler.tar")
406
+ Dir.chdir(opts[:package_compiler]) do
407
+ sh "tar -cf #{tmp_package_compiler_tar} *"
408
+ @package_compiler_tar = tmp_package_compiler_tar
409
+ end
410
+ end
411
+
412
+ end
413
+
414
+ def build_all_deps
415
+ @logger.info "Build all bosh packages with dependencies from source"
416
+ @logger.info "Execute 'rake all:build_with_deps' in bosh/ directory"
417
+ end
418
+
419
+ def create_release_tarball
420
+ @logger.info("Copy bosh/release/config/microbosh-dev-template.yml to bosh/release/config/dev.yml")
421
+ @logger.info("Then execute 'bosh create release --force --with-tarball'")
422
+ @logger.info("The release tar will be in bosh/release/dev_releases/micro-bosh*.tgz")
423
+ @logger.info("The release manifest is at bosh/release/micro/vsphere.yml")
424
+ end
425
+
426
+ def convert_stemcell_to_micro
427
+ # SCP upload _release.tgz, _package_compiler.tar, _release.yml, micro.sh
428
+ upload_file @package_compiler_tar, "/home/vcap/_package_compiler.tar"
429
+ upload_file @release_tar, "/home/vcap/_release.tgz"
430
+ upload_file @release_manifest, "/home/vcap/_release.yml"
431
+ upload_file @micro_path, "/home/vcap/micro.sh"
432
+ # SSH execute micro.sh
433
+ @logger.info ssh_execute("./micro.sh")
434
+
435
+ # SCP download apply.spec
436
+ download_file "/var/vcap/micro/apply_spec.yml"
437
+ @stemcell_files << File.join(@prefix, "apply_spec.yml")
438
+ end
439
+
440
+ end
441
+ end
442
+
443
+ require 'stemcell/builders/ubuntu'
444
+ require 'stemcell/builders/redhat'
445
+ require 'stemcell/builders/centos'
@@ -0,0 +1,33 @@
1
+ require 'stemcell/builder'
2
+
3
+ module Bosh::Agent::StemCell
4
+
5
+ # This is concrete Stemcell builder for creating a Centos stemcell
6
+ # It creates a CentOS-6.3. The options passed are merged with
7
+ # {
8
+ # :type => 'centos',
9
+ # :iso => 'http://www.mirrorservice.org/sites/mirror.centos.org/6.3/isos/x86_64/CentOS-6.3-x86_64-minimal.iso',
10
+ # :iso_md5 => '087713752fa88c03a5e8471c661ad1a2',
11
+ # :iso_filename => 'CentOS-6.3-x86_64-minimal.iso'
12
+ # }
13
+ class CentosBuilder < BaseBuilder
14
+
15
+ def type
16
+ "centos"
17
+ end
18
+
19
+ def pre_shutdown_hook
20
+ super()
21
+ download_file "/var/vcap/bosh/stemcell_yum_list_installed.out"
22
+ # add file to the list of files to be packaged
23
+ @stemcell_files << File.join(@prefix, "stemcell_yum_list_installed.out")
24
+ end
25
+
26
+ def init_default_iso
27
+ @iso = "http://www.mirrorservice.org/sites/mirror.centos.org/6.3/isos/x86_64/CentOS-6.3-x86_64-minimal.iso"
28
+ @iso_md5 = "087713752fa88c03a5e8471c661ad1a2"
29
+ @iso_filename = "CentOS-6.3-x86_64-minimal.iso"
30
+ end
31
+
32
+ end
33
+ end