stemcell_builder 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/.rvmrc +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +22 -0
- data/README.md +123 -0
- data/Rakefile +10 -0
- data/assets/box.ovf.erb +81 -0
- data/assets/stemcell_mf_schema.yaml +30 -0
- data/bin/stemcell_builder +138 -0
- data/lib/stemcell.rb +3 -0
- data/lib/stemcell/builder.rb +445 -0
- data/lib/stemcell/builders/centos.rb +33 -0
- data/lib/stemcell/builders/redhat.rb +34 -0
- data/lib/stemcell/builders/ubuntu.rb +36 -0
- data/lib/stemcell/const.rb +12 -0
- data/lib/stemcell/version.rb +10 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/stemcell_builder/builder_spec.rb +186 -0
- data/spec/stemcell_builder/centos_spec.rb +39 -0
- data/spec/stemcell_builder/redhat_spec.rb +53 -0
- data/spec/stemcell_builder/ubuntu_spec.rb +38 -0
- data/stemcell_builder.gemspec +42 -0
- data/templates/centos/_60-bosh-sysctl.conf +5 -0
- data/templates/centos/_empty_state.yml +9 -0
- data/templates/centos/_monitrc +8 -0
- data/templates/centos/_ntpdate +10 -0
- data/templates/centos/_runonce +46 -0
- data/templates/centos/_sysstat +18 -0
- data/templates/centos/_variables.sh.erb +31 -0
- data/templates/centos/base.sh +23 -0
- data/templates/centos/bosh_agent.sh +39 -0
- data/templates/centos/cleanup.sh +28 -0
- data/templates/centos/definition.rb.erb +37 -0
- data/templates/centos/harden.sh +8 -0
- data/templates/centos/ks.cfg +43 -0
- data/templates/centos/micro.sh +57 -0
- data/templates/centos/monit.sh +21 -0
- data/templates/centos/postinstall.sh +27 -0
- data/templates/centos/ruby.sh +42 -0
- data/templates/centos/setup-bosh.sh +20 -0
- data/templates/centos/sudo.sh +13 -0
- data/templates/centos/timestamp.sh +15 -0
- data/templates/centos/vmware-tools.sh +17 -0
- data/templates/centos/zerodisk.sh +9 -0
- data/templates/noop/erbtest.txt.erb +1 -0
- data/templates/noop/test.txt +1 -0
- data/templates/redhat/_60-bosh-sysctl.conf +5 -0
- data/templates/redhat/_empty_state.yml +9 -0
- data/templates/redhat/_monitrc +8 -0
- data/templates/redhat/_ntpdate +10 -0
- data/templates/redhat/_runonce +46 -0
- data/templates/redhat/_sysstat +18 -0
- data/templates/redhat/_variables.sh.erb +31 -0
- data/templates/redhat/base.sh +41 -0
- data/templates/redhat/bosh_agent.sh +37 -0
- data/templates/redhat/cleanup.sh +30 -0
- data/templates/redhat/definition.rb.erb +38 -0
- data/templates/redhat/harden.sh +8 -0
- data/templates/redhat/ks.cfg +86 -0
- data/templates/redhat/micro.sh +57 -0
- data/templates/redhat/monit.sh +21 -0
- data/templates/redhat/postinstall.sh +27 -0
- data/templates/redhat/rhnreg.sh.erb +15 -0
- data/templates/redhat/ruby.sh +42 -0
- data/templates/redhat/setup-bosh.sh +20 -0
- data/templates/redhat/sudo.sh +13 -0
- data/templates/redhat/timestamp.sh +15 -0
- data/templates/redhat/vmware-tools.sh +17 -0
- data/templates/redhat/zerodisk.sh +9 -0
- data/templates/ubuntu/_60-bosh-sysctl.conf +5 -0
- data/templates/ubuntu/_empty_state.yml +9 -0
- data/templates/ubuntu/_helpers.sh +40 -0
- data/templates/ubuntu/_monitrc +8 -0
- data/templates/ubuntu/_ntpdate +10 -0
- data/templates/ubuntu/_runonce +46 -0
- data/templates/ubuntu/_sysstat +18 -0
- data/templates/ubuntu/_variables.sh.erb +30 -0
- data/templates/ubuntu/apt-upgrade.sh +19 -0
- data/templates/ubuntu/base-stemcell.sh +95 -0
- data/templates/ubuntu/bosh_agent.sh +39 -0
- data/templates/ubuntu/definition.rb.erb +63 -0
- data/templates/ubuntu/harden.sh +9 -0
- data/templates/ubuntu/micro.sh +57 -0
- data/templates/ubuntu/monit.sh +22 -0
- data/templates/ubuntu/network-cleanup.sh +17 -0
- data/templates/ubuntu/postinstall.sh +45 -0
- data/templates/ubuntu/preseed.cfg +87 -0
- data/templates/ubuntu/ruby.sh +54 -0
- data/templates/ubuntu/setup-bosh.sh +14 -0
- data/templates/ubuntu/sudo.sh +14 -0
- data/templates/ubuntu/timestamp.sh +13 -0
- data/templates/ubuntu/vmware-tools.sh +22 -0
- data/templates/ubuntu/zero-disk.sh +10 -0
- metadata +375 -0
data/lib/stemcell.rb
ADDED
@@ -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
|