bosh-stemcell 1.5.0.pre.1113

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.rspec +3 -0
  2. data/README.md +104 -0
  3. data/Vagrantfile +37 -0
  4. data/bosh-stemcell.gemspec +28 -0
  5. data/lib/bosh/stemcell.rb +4 -0
  6. data/lib/bosh/stemcell/archive.rb +59 -0
  7. data/lib/bosh/stemcell/archive_filename.rb +29 -0
  8. data/lib/bosh/stemcell/aws/ami.rb +58 -0
  9. data/lib/bosh/stemcell/aws/light_stemcell.rb +44 -0
  10. data/lib/bosh/stemcell/aws/region.rb +15 -0
  11. data/lib/bosh/stemcell/builder_command.rb +174 -0
  12. data/lib/bosh/stemcell/builder_options.rb +85 -0
  13. data/lib/bosh/stemcell/disk_image.rb +61 -0
  14. data/lib/bosh/stemcell/infrastructure.rb +49 -0
  15. data/lib/bosh/stemcell/operating_system.rb +31 -0
  16. data/lib/bosh/stemcell/stage_collection.rb +154 -0
  17. data/lib/bosh/stemcell/stage_runner.rb +53 -0
  18. data/lib/bosh/stemcell/version.rb +5 -0
  19. data/lib/monkeypatch/serverspec/backend/exec.rb +86 -0
  20. data/spec/assets/fake-stemcell-aws.tgz +0 -0
  21. data/spec/assets/fake-stemcell-vsphere.tgz +0 -0
  22. data/spec/assets/light-fake-stemcell-aws.tgz +0 -0
  23. data/spec/bosh/monkeypatch/serverspec/backend/exec_spec.rb +46 -0
  24. data/spec/bosh/stemcell/archive_filename_spec.rb +42 -0
  25. data/spec/bosh/stemcell/archive_spec.rb +98 -0
  26. data/spec/bosh/stemcell/aws/ami_spec.rb +30 -0
  27. data/spec/bosh/stemcell/aws/light_stemcell_spec.rb +94 -0
  28. data/spec/bosh/stemcell/aws/region_spec.rb +12 -0
  29. data/spec/bosh/stemcell/builder_command_spec.rb +241 -0
  30. data/spec/bosh/stemcell/builder_options_spec.rb +201 -0
  31. data/spec/bosh/stemcell/disk_image_spec.rb +163 -0
  32. data/spec/bosh/stemcell/infrastructure_spec.rb +66 -0
  33. data/spec/bosh/stemcell/operating_system_spec.rb +47 -0
  34. data/spec/bosh/stemcell/stage_collection_spec.rb +213 -0
  35. data/spec/bosh/stemcell/stage_runner_spec.rb +141 -0
  36. data/spec/bosh/stemcell/version_spec.rb +12 -0
  37. data/spec/bosh/stemcell_spec.rb +6 -0
  38. data/spec/spec_helper.rb +6 -0
  39. data/spec/stemcells/aws_spec.rb +9 -0
  40. data/spec/stemcells/centos_spec.rb +131 -0
  41. data/spec/stemcells/openstack_spec.rb +9 -0
  42. data/spec/stemcells/ubuntu_spec.rb +143 -0
  43. data/spec/stemcells/vsphere_spec.rb +9 -0
  44. data/spec/support/rspec_fire.rb +9 -0
  45. data/spec/support/serverspec.rb +4 -0
  46. data/spec/support/spec_assets.rb +11 -0
  47. data/spec/support/stemcell_image.rb +26 -0
  48. data/spec/support/stemcell_shared_examples.rb +43 -0
  49. data/spec/support/stub_env.rb +5 -0
  50. 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
@@ -0,0 +1,5 @@
1
+ module Bosh
2
+ module Stemcell
3
+ VERSION = '1.5.0.pre.1113'
4
+ end
5
+ end