bosh-stemcell 1.5.0.pre.1113
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.
- data/.rspec +3 -0
- data/README.md +104 -0
- data/Vagrantfile +37 -0
- data/bosh-stemcell.gemspec +28 -0
- data/lib/bosh/stemcell.rb +4 -0
- data/lib/bosh/stemcell/archive.rb +59 -0
- data/lib/bosh/stemcell/archive_filename.rb +29 -0
- data/lib/bosh/stemcell/aws/ami.rb +58 -0
- data/lib/bosh/stemcell/aws/light_stemcell.rb +44 -0
- data/lib/bosh/stemcell/aws/region.rb +15 -0
- data/lib/bosh/stemcell/builder_command.rb +174 -0
- data/lib/bosh/stemcell/builder_options.rb +85 -0
- data/lib/bosh/stemcell/disk_image.rb +61 -0
- data/lib/bosh/stemcell/infrastructure.rb +49 -0
- data/lib/bosh/stemcell/operating_system.rb +31 -0
- data/lib/bosh/stemcell/stage_collection.rb +154 -0
- data/lib/bosh/stemcell/stage_runner.rb +53 -0
- data/lib/bosh/stemcell/version.rb +5 -0
- data/lib/monkeypatch/serverspec/backend/exec.rb +86 -0
- data/spec/assets/fake-stemcell-aws.tgz +0 -0
- data/spec/assets/fake-stemcell-vsphere.tgz +0 -0
- data/spec/assets/light-fake-stemcell-aws.tgz +0 -0
- data/spec/bosh/monkeypatch/serverspec/backend/exec_spec.rb +46 -0
- data/spec/bosh/stemcell/archive_filename_spec.rb +42 -0
- data/spec/bosh/stemcell/archive_spec.rb +98 -0
- data/spec/bosh/stemcell/aws/ami_spec.rb +30 -0
- data/spec/bosh/stemcell/aws/light_stemcell_spec.rb +94 -0
- data/spec/bosh/stemcell/aws/region_spec.rb +12 -0
- data/spec/bosh/stemcell/builder_command_spec.rb +241 -0
- data/spec/bosh/stemcell/builder_options_spec.rb +201 -0
- data/spec/bosh/stemcell/disk_image_spec.rb +163 -0
- data/spec/bosh/stemcell/infrastructure_spec.rb +66 -0
- data/spec/bosh/stemcell/operating_system_spec.rb +47 -0
- data/spec/bosh/stemcell/stage_collection_spec.rb +213 -0
- data/spec/bosh/stemcell/stage_runner_spec.rb +141 -0
- data/spec/bosh/stemcell/version_spec.rb +12 -0
- data/spec/bosh/stemcell_spec.rb +6 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/stemcells/aws_spec.rb +9 -0
- data/spec/stemcells/centos_spec.rb +131 -0
- data/spec/stemcells/openstack_spec.rb +9 -0
- data/spec/stemcells/ubuntu_spec.rb +143 -0
- data/spec/stemcells/vsphere_spec.rb +9 -0
- data/spec/support/rspec_fire.rb +9 -0
- data/spec/support/serverspec.rb +4 -0
- data/spec/support/spec_assets.rb +11 -0
- data/spec/support/stemcell_image.rb +26 -0
- data/spec/support/stemcell_shared_examples.rb +43 -0
- data/spec/support/stub_env.rb +5 -0
- metadata +236 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'bosh_agent/version'
|
3
|
+
require 'bosh/stemcell/archive_filename'
|
4
|
+
|
5
|
+
module Bosh::Stemcell
|
6
|
+
class BuilderOptions
|
7
|
+
def initialize(env, options)
|
8
|
+
@environment = env
|
9
|
+
@infrastructure = options.fetch(:infrastructure)
|
10
|
+
@operating_system = options.fetch(:operating_system)
|
11
|
+
|
12
|
+
@stemcell_version = options.fetch(:stemcell_version)
|
13
|
+
@image_create_disk_size = options.fetch(:disk_size, infrastructure.default_disk_size)
|
14
|
+
@bosh_micro_release_tgz_path = options.fetch(:tarball)
|
15
|
+
end
|
16
|
+
|
17
|
+
def default
|
18
|
+
{
|
19
|
+
'stemcell_name' => "bosh-#{infrastructure.name}-#{infrastructure.hypervisor}-#{operating_system.name}",
|
20
|
+
'stemcell_tgz' => archive_filename.to_s,
|
21
|
+
'stemcell_image_name' => stemcell_image_name,
|
22
|
+
'stemcell_version' => stemcell_version,
|
23
|
+
'stemcell_hypervisor' => infrastructure.hypervisor,
|
24
|
+
'stemcell_infrastructure' => infrastructure.name,
|
25
|
+
'stemcell_operating_system' => operating_system.name,
|
26
|
+
'bosh_protocol_version' => Bosh::Agent::BOSH_PROTOCOL,
|
27
|
+
'ruby_bin' => ruby_bin,
|
28
|
+
'bosh_release_src_dir' => File.join(source_root, 'release/src/bosh'),
|
29
|
+
'bosh_agent_src_dir' => File.join(source_root, 'bosh_agent'),
|
30
|
+
'image_create_disk_size' => image_create_disk_size
|
31
|
+
}.merge(bosh_micro_options).merge(environment_variables).merge(vsphere_options)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader(
|
37
|
+
:environment,
|
38
|
+
:infrastructure,
|
39
|
+
:operating_system,
|
40
|
+
:stemcell_version,
|
41
|
+
:image_create_disk_size,
|
42
|
+
:bosh_micro_release_tgz_path
|
43
|
+
)
|
44
|
+
|
45
|
+
def vsphere_options
|
46
|
+
if infrastructure.name == 'vsphere'
|
47
|
+
{ 'image_vsphere_ovf_ovftool_path' => environment['OVFTOOL'] }
|
48
|
+
else
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def environment_variables
|
54
|
+
{
|
55
|
+
'UBUNTU_ISO' => environment['UBUNTU_ISO'],
|
56
|
+
'UBUNTU_MIRROR' => environment['UBUNTU_MIRROR'],
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def bosh_micro_options
|
61
|
+
{
|
62
|
+
'bosh_micro_enabled' => 'yes',
|
63
|
+
'bosh_micro_package_compiler_path' => File.join(source_root, 'bosh-release'),
|
64
|
+
'bosh_micro_manifest_yml_path' => File.join(source_root, 'release', 'micro', "#{infrastructure.name}.yml"),
|
65
|
+
'bosh_micro_release_tgz_path' => bosh_micro_release_tgz_path,
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def archive_filename
|
70
|
+
ArchiveFilename.new(stemcell_version, infrastructure, operating_system, 'bosh-stemcell', false)
|
71
|
+
end
|
72
|
+
|
73
|
+
def stemcell_image_name
|
74
|
+
"#{infrastructure.name}-#{infrastructure.hypervisor}-#{operating_system.name}.raw"
|
75
|
+
end
|
76
|
+
|
77
|
+
def ruby_bin
|
78
|
+
environment['RUBY_BIN'] || File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
79
|
+
end
|
80
|
+
|
81
|
+
def source_root
|
82
|
+
File.expand_path('../../../../..', __FILE__)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'bosh/core/shell'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module Bosh::Stemcell
|
5
|
+
class DiskImage
|
6
|
+
|
7
|
+
attr_reader :image_mount_point
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
@image_file_path = options.fetch(:image_file_path)
|
11
|
+
@image_mount_point = options.fetch(:image_mount_point, Dir.mktmpdir)
|
12
|
+
@verbose = options.fetch(:verbose, false)
|
13
|
+
@shell = Bosh::Core::Shell.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def mount
|
17
|
+
device_path = stemcell_loopback_device_name
|
18
|
+
mount_command = "sudo mount #{device_path} #{image_mount_point}"
|
19
|
+
shell.run(mount_command, output_command: verbose)
|
20
|
+
rescue => e
|
21
|
+
raise e unless e.message.include?(mount_command)
|
22
|
+
|
23
|
+
sleep 0.5
|
24
|
+
shell.run(mount_command, output_command: verbose)
|
25
|
+
end
|
26
|
+
|
27
|
+
def unmount
|
28
|
+
shell.run("sudo umount #{image_mount_point}", output_command: verbose)
|
29
|
+
ensure
|
30
|
+
unmap_image
|
31
|
+
end
|
32
|
+
|
33
|
+
def while_mounted
|
34
|
+
mount
|
35
|
+
yield self
|
36
|
+
ensure
|
37
|
+
unmount
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :image_file_path, :verbose, :shell, :device
|
43
|
+
|
44
|
+
def stemcell_loopback_device_name
|
45
|
+
split_output = map_image.split(' ')
|
46
|
+
device_name = split_output[2]
|
47
|
+
|
48
|
+
File.join('/dev/mapper', device_name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def map_image
|
52
|
+
@device = shell.run("sudo losetup --show --find #{image_file_path}", output_command: verbose)
|
53
|
+
shell.run("sudo kpartx -av #{device}", output_command: verbose)
|
54
|
+
end
|
55
|
+
|
56
|
+
def unmap_image
|
57
|
+
shell.run("sudo kpartx -dv #{device}", output_command: verbose)
|
58
|
+
shell.run("sudo losetup -dv #{device}", output_command: verbose)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Bosh::Stemcell
|
2
|
+
module Infrastructure
|
3
|
+
def self.for(name)
|
4
|
+
case name
|
5
|
+
when 'openstack'
|
6
|
+
OpenStack.new
|
7
|
+
when 'aws'
|
8
|
+
Aws.new
|
9
|
+
when 'vsphere'
|
10
|
+
Vsphere.new
|
11
|
+
else
|
12
|
+
raise ArgumentError.new("invalid infrastructure: #{name}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Base
|
17
|
+
attr_reader :name, :hypervisor, :default_disk_size
|
18
|
+
|
19
|
+
def initialize(options = {})
|
20
|
+
@name = options.fetch(:name)
|
21
|
+
@supports_light_stemcell = options.fetch(:supports_light_stemcell, false)
|
22
|
+
@hypervisor = options.fetch(:hypervisor)
|
23
|
+
@default_disk_size = options.fetch(:default_disk_size)
|
24
|
+
end
|
25
|
+
|
26
|
+
def light?
|
27
|
+
@supports_light_stemcell
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class OpenStack < Base
|
32
|
+
def initialize
|
33
|
+
super(name: 'openstack', hypervisor: 'kvm', default_disk_size: 10240)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Vsphere < Base
|
38
|
+
def initialize
|
39
|
+
super(name: 'vsphere', hypervisor: 'esxi', default_disk_size: 2048)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Aws < Base
|
44
|
+
def initialize
|
45
|
+
super(name: 'aws', hypervisor: 'xen', supports_light_stemcell: true, default_disk_size: 2048)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bosh::Stemcell
|
2
|
+
module OperatingSystem
|
3
|
+
def self.for(operating_system_name)
|
4
|
+
case operating_system_name
|
5
|
+
when 'centos' then Centos.new
|
6
|
+
when 'ubuntu' then Ubuntu.new
|
7
|
+
else raise ArgumentError.new("invalid operating system: #{operating_system_name}")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Base
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@name = options.fetch(:name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Centos < Base
|
20
|
+
def initialize
|
21
|
+
super(name: 'centos')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Ubuntu < Base
|
26
|
+
def initialize
|
27
|
+
super(name: 'ubuntu')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'bosh/stemcell/infrastructure'
|
2
|
+
require 'bosh/stemcell/operating_system'
|
3
|
+
|
4
|
+
module Bosh::Stemcell
|
5
|
+
class StageCollection
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@infrastructure = options.fetch(:infrastructure)
|
9
|
+
@operating_system = options.fetch(:operating_system)
|
10
|
+
end
|
11
|
+
|
12
|
+
def operating_system_stages
|
13
|
+
case operating_system
|
14
|
+
when OperatingSystem::Centos then
|
15
|
+
[:base_centos, :base_yum] + hacked_centos_common
|
16
|
+
when OperatingSystem::Ubuntu then
|
17
|
+
[:base_debootstrap, :base_apt] + common_stages
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def infrastructure_stages
|
22
|
+
case infrastructure
|
23
|
+
when Infrastructure::Aws then
|
24
|
+
aws_stages
|
25
|
+
when Infrastructure::OpenStack then
|
26
|
+
openstack_stages
|
27
|
+
when Infrastructure::Vsphere then
|
28
|
+
operating_system.instance_of?(OperatingSystem::Centos) ? hacked_centos_vsphere : vsphere_stages
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :infrastructure, :operating_system
|
35
|
+
|
36
|
+
def hacked_centos_common
|
37
|
+
[
|
38
|
+
# Bosh steps
|
39
|
+
:bosh_users,
|
40
|
+
:bosh_monit,
|
41
|
+
:bosh_ruby,
|
42
|
+
:bosh_agent,
|
43
|
+
#:bosh_sysstat,
|
44
|
+
#:bosh_sysctl,
|
45
|
+
#:bosh_ntpdate,
|
46
|
+
:bosh_sudoers,
|
47
|
+
# Micro BOSH
|
48
|
+
:bosh_micro,
|
49
|
+
# Install GRUB/kernel/etc
|
50
|
+
:system_grub,
|
51
|
+
#:system_kernel,
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def hacked_centos_vsphere
|
56
|
+
[
|
57
|
+
#:system_open_vm_tools,
|
58
|
+
:system_parameters,
|
59
|
+
:bosh_clean,
|
60
|
+
#:bosh_harden,
|
61
|
+
#:bosh_dpkg_list,
|
62
|
+
:image_create,
|
63
|
+
:image_install_grub,
|
64
|
+
:image_vsphere_vmx,
|
65
|
+
:image_vsphere_ovf,
|
66
|
+
:image_vsphere_prepare_stemcell,
|
67
|
+
:stemcell
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def common_stages
|
72
|
+
[
|
73
|
+
# Bosh steps
|
74
|
+
:bosh_users,
|
75
|
+
:bosh_monit,
|
76
|
+
:bosh_ruby,
|
77
|
+
:bosh_agent,
|
78
|
+
:bosh_sysstat,
|
79
|
+
:bosh_sysctl,
|
80
|
+
:bosh_ntpdate,
|
81
|
+
:bosh_sudoers,
|
82
|
+
# Micro BOSH
|
83
|
+
:bosh_micro,
|
84
|
+
# Install GRUB/kernel/etc
|
85
|
+
:system_grub,
|
86
|
+
:system_kernel,
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
def aws_stages
|
91
|
+
[
|
92
|
+
# Misc
|
93
|
+
:system_aws_network,
|
94
|
+
:system_aws_clock,
|
95
|
+
:system_aws_modules,
|
96
|
+
:system_parameters,
|
97
|
+
# Finalisation
|
98
|
+
:bosh_clean,
|
99
|
+
:bosh_harden,
|
100
|
+
:bosh_harden_ssh,
|
101
|
+
:bosh_dpkg_list,
|
102
|
+
# Image/bootloader
|
103
|
+
:image_create,
|
104
|
+
:image_install_grub,
|
105
|
+
:image_aws_update_grub,
|
106
|
+
:image_aws_prepare_stemcell,
|
107
|
+
# Final stemcell
|
108
|
+
:stemcell
|
109
|
+
]
|
110
|
+
end
|
111
|
+
|
112
|
+
def openstack_stages
|
113
|
+
[
|
114
|
+
# Misc
|
115
|
+
:system_openstack_network,
|
116
|
+
:system_openstack_clock,
|
117
|
+
:system_openstack_modules,
|
118
|
+
:system_parameters,
|
119
|
+
# Finalisation,
|
120
|
+
:bosh_clean,
|
121
|
+
:bosh_harden,
|
122
|
+
:bosh_harden_ssh,
|
123
|
+
:bosh_dpkg_list,
|
124
|
+
# Image/bootloader
|
125
|
+
:image_create,
|
126
|
+
:image_install_grub,
|
127
|
+
:image_openstack_qcow2,
|
128
|
+
:image_openstack_prepare_stemcell,
|
129
|
+
# Final stemcell
|
130
|
+
:stemcell_openstack
|
131
|
+
]
|
132
|
+
end
|
133
|
+
|
134
|
+
def vsphere_stages
|
135
|
+
[
|
136
|
+
:system_open_vm_tools,
|
137
|
+
# Misc
|
138
|
+
:system_parameters,
|
139
|
+
# Finalisation
|
140
|
+
:bosh_clean,
|
141
|
+
:bosh_harden,
|
142
|
+
:bosh_dpkg_list,
|
143
|
+
# Image/bootloader
|
144
|
+
:image_create,
|
145
|
+
:image_install_grub,
|
146
|
+
:image_vsphere_vmx,
|
147
|
+
:image_vsphere_ovf,
|
148
|
+
:image_vsphere_prepare_stemcell,
|
149
|
+
# Final stemcell
|
150
|
+
:stemcell
|
151
|
+
]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'bosh/core/shell'
|
2
|
+
|
3
|
+
module Bosh::Stemcell
|
4
|
+
class StageRunner
|
5
|
+
def initialize(options)
|
6
|
+
@build_path = options.fetch(:build_path)
|
7
|
+
@command_env = options.fetch(:command_env)
|
8
|
+
@settings_file = options.fetch(:settings_file)
|
9
|
+
@work_path = options.fetch(:work_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_and_apply(stages)
|
13
|
+
configure(stages)
|
14
|
+
apply(stages)
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure(stages)
|
18
|
+
stages.each do |stage|
|
19
|
+
stage_config_script = File.join(build_path, 'stages', stage.to_s, 'config.sh')
|
20
|
+
|
21
|
+
puts "=== Configuring '#{stage}' stage ==="
|
22
|
+
if File.exists?(stage_config_script) && File.executable?(stage_config_script)
|
23
|
+
run_sudo_with_command_env("#{stage_config_script} #{settings_file}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def apply(stages)
|
29
|
+
work_directory = File.join(work_path, 'work')
|
30
|
+
|
31
|
+
stages.each do |stage|
|
32
|
+
FileUtils.mkdir_p(work_directory)
|
33
|
+
|
34
|
+
puts "=== Applying '#{stage}' stage ==="
|
35
|
+
puts "== Started #{Time.now.strftime('%a %b %e %H:%M:%S %Z %Y')} =="
|
36
|
+
|
37
|
+
stage_apply_script = File.join(build_path, 'stages', stage.to_s, 'apply.sh')
|
38
|
+
|
39
|
+
run_sudo_with_command_env("#{stage_apply_script} #{work_directory}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_reader :stages, :build_path, :command_env, :settings_file, :work_path
|
46
|
+
|
47
|
+
def run_sudo_with_command_env(command)
|
48
|
+
shell = Bosh::Core::Shell.new
|
49
|
+
|
50
|
+
shell.run("sudo #{command_env} #{command} 2>&1")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|