bosh-bootstrap 0.10.2 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. data/.rspec +1 -0
  2. data/.travis.yml +0 -1
  3. data/ChangeLog.md +23 -4
  4. data/Gemfile +5 -2
  5. data/Guardfile +2 -0
  6. data/README.md +209 -197
  7. data/TODO.md +55 -0
  8. data/bosh-bootstrap.gemspec +5 -12
  9. data/lib/bosh/cli/commands/bootstrap.rb +42 -0
  10. data/lib/bosh-bootstrap/cli/commands/delete.rb +26 -0
  11. data/lib/bosh-bootstrap/cli/commands/deploy.rb +89 -0
  12. data/lib/bosh-bootstrap/cli/commands/ssh.rb +32 -0
  13. data/lib/bosh-bootstrap/cli/helpers/bundle.rb +12 -0
  14. data/lib/bosh-bootstrap/cli/helpers/interactions.rb +15 -0
  15. data/lib/bosh-bootstrap/cli/helpers/settings.rb +61 -0
  16. data/lib/bosh-bootstrap/cli/helpers.rb +11 -0
  17. data/lib/bosh-bootstrap/key_pair.rb +21 -0
  18. data/lib/bosh-bootstrap/microbosh.rb +74 -0
  19. data/lib/bosh-bootstrap/microbosh_providers/aws.rb +104 -0
  20. data/lib/bosh-bootstrap/microbosh_providers/base.rb +50 -0
  21. data/lib/bosh-bootstrap/microbosh_providers/openstack.rb +61 -0
  22. data/lib/bosh-bootstrap/microbosh_providers/vsphere.rb +78 -0
  23. data/lib/bosh-bootstrap/microbosh_providers.rb +11 -0
  24. data/lib/bosh-bootstrap/network.rb +33 -0
  25. data/lib/bosh-bootstrap/network_providers/aws.rb +28 -0
  26. data/lib/bosh-bootstrap/network_providers/dummy.rb +10 -0
  27. data/lib/bosh-bootstrap/network_providers/openstack.rb +28 -0
  28. data/lib/bosh-bootstrap/network_providers.rb +11 -0
  29. data/lib/bosh-bootstrap/version.rb +1 -1
  30. data/lib/bosh-bootstrap.rb +3 -4
  31. data/spec/assets/microbosh_yml/micro_bosh.aws_ec2.yml +37 -0
  32. data/spec/assets/microbosh_yml/micro_bosh.aws_vpc.yml +39 -0
  33. data/spec/assets/microbosh_yml/micro_bosh.openstack.yml +30 -0
  34. data/spec/assets/microbosh_yml/micro_bosh.vsphere.yml +34 -0
  35. data/spec/integration/aws/aws_ec2_basic_spec.rb +39 -0
  36. data/spec/integration/aws/aws_helpers.rb +8 -61
  37. data/spec/spec_helper.rb +8 -3
  38. data/spec/support/capture_stdout.rb +18 -0
  39. data/spec/unit/cli/bootstrap_spec.rb +41 -0
  40. data/spec/unit/commands/delete_spec.rb +20 -0
  41. data/spec/unit/commands/deploy_spec.rb +64 -0
  42. data/spec/unit/commands/ssh_spec.rb +19 -0
  43. data/spec/unit/key_pair_spec.rb +13 -0
  44. data/spec/unit/microbosh_providers/aws_spec.rb +68 -0
  45. data/spec/unit/microbosh_providers/openstack_spec.rb +27 -0
  46. data/spec/unit/microbosh_providers/vsphere_spec.rb +42 -0
  47. data/spec/unit/microbosh_spec.rb +27 -0
  48. data/spec/unit/network_providers/aws_spec.rb +29 -0
  49. data/spec/unit/network_providers/openstack_spec.rb +29 -0
  50. data/spec/unit/network_spec.rb +17 -0
  51. metadata +71 -235
  52. data/CleanupCi.md +0 -8
  53. data/bin/bosh-bootstrap +0 -8
  54. data/docs/README.md +0 -3
  55. data/docs/devstack-openstack-tutorial.md +0 -215
  56. data/lib/bosh/providers/README.md +0 -5
  57. data/lib/bosh/providers/aws.rb +0 -258
  58. data/lib/bosh/providers/base_provider.rb +0 -48
  59. data/lib/bosh/providers/openstack.rb +0 -79
  60. data/lib/bosh/providers.rb +0 -21
  61. data/lib/bosh-bootstrap/cli.rb +0 -1347
  62. data/lib/bosh-bootstrap/commander/README.md +0 -47
  63. data/lib/bosh-bootstrap/commander/command.rb +0 -25
  64. data/lib/bosh-bootstrap/commander/commands.rb +0 -80
  65. data/lib/bosh-bootstrap/commander/local_server.rb +0 -68
  66. data/lib/bosh-bootstrap/commander/remote_script_command.rb +0 -51
  67. data/lib/bosh-bootstrap/commander/remote_server.rb +0 -137
  68. data/lib/bosh-bootstrap/commander/upload_command.rb +0 -17
  69. data/lib/bosh-bootstrap/commander.rb +0 -9
  70. data/lib/bosh-bootstrap/helpers/fog_setup.rb +0 -50
  71. data/lib/bosh-bootstrap/helpers/settings.rb +0 -99
  72. data/lib/bosh-bootstrap/helpers/settings_setter.rb +0 -41
  73. data/lib/bosh-bootstrap/helpers.rb +0 -3
  74. data/lib/bosh-bootstrap/stages/stage_micro_bosh_delete/bosh_micro_delete +0 -19
  75. data/lib/bosh-bootstrap/stages/stage_micro_bosh_delete.rb +0 -90
  76. data/lib/bosh-bootstrap/stages/stage_micro_bosh_deploy/bosh_micro_deploy +0 -79
  77. data/lib/bosh-bootstrap/stages/stage_micro_bosh_deploy/install_key_pair_for_user +0 -23
  78. data/lib/bosh-bootstrap/stages/stage_micro_bosh_deploy.rb +0 -146
  79. data/lib/bosh-bootstrap/stages/stage_micro_bosh_download/download_micro_bosh_stemcell +0 -93
  80. data/lib/bosh-bootstrap/stages/stage_micro_bosh_download.rb +0 -139
  81. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/configure_git +0 -25
  82. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/create_vcap_user +0 -79
  83. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_base_packages +0 -30
  84. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_bosh +0 -11
  85. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_bosh_plugins +0 -25
  86. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_hub +0 -26
  87. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_ruby +0 -30
  88. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/install_useful_gems +0 -29
  89. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm/validate_bosh_deployer +0 -18
  90. data/lib/bosh-bootstrap/stages/stage_prepare_inception_vm.rb +0 -69
  91. data/lib/bosh-bootstrap/stages/stage_salted_password/convert_salted_password +0 -11
  92. data/lib/bosh-bootstrap/stages/stage_salted_password.rb +0 -51
  93. data/lib/bosh-bootstrap/stages/stage_setup_new_bosh/setup_bosh_user +0 -29
  94. data/lib/bosh-bootstrap/stages/stage_setup_new_bosh.rb +0 -51
  95. data/lib/bosh-bootstrap/stages/stage_validate_inception_vm/validate_ubuntu +0 -6
  96. data/lib/bosh-bootstrap/stages/stage_validate_inception_vm.rb +0 -39
  97. data/lib/bosh-bootstrap/stages.rb +0 -10
  98. data/spec/assets/bosh/public_stemcells/aws_micro.out +0 -7
  99. data/spec/assets/micro_bosh_yml/micro_bosh.aws_ec2.yml +0 -35
  100. data/spec/assets/micro_bosh_yml/micro_bosh.aws_vpc.yml +0 -37
  101. data/spec/integration/aws/aws_basic_spec.rb +0 -39
  102. data/spec/integration/aws/aws_edge_prebuilt_ami_spec.rb +0 -46
  103. data/spec/integration/aws/aws_edge_prebuilt_spec.rb +0 -46
  104. data/spec/integration/aws/aws_edge_spec.rb +0 -45
  105. data/spec/unit/aws_spec.rb +0 -177
  106. data/spec/unit/bosh/providers/aws_spec.rb +0 -174
  107. data/spec/unit/cli_spec.rb +0 -134
  108. data/spec/unit/cli_ssh_spec.rb +0 -95
  109. data/spec/unit/cli_upgrade_inception_spec.rb +0 -29
  110. data/spec/unit/settings_setter_spec.rb +0 -29
  111. data/vendor/cache/POpen4-0.1.4.gem +0 -0
  112. data/vendor/cache/Platform-0.4.0.gem +0 -0
  113. data/vendor/cache/activesupport-3.2.8.gem +0 -0
  114. data/vendor/cache/awesome_print-1.1.0.gem +0 -0
  115. data/vendor/cache/aws-s3-0.6.3.gem +0 -0
  116. data/vendor/cache/blobstore_client-0.4.0.gem +0 -0
  117. data/vendor/cache/bosh_cli-1.0.3.gem +0 -0
  118. data/vendor/cache/bosh_common-0.5.4.gem +0 -0
  119. data/vendor/cache/builder-3.2.0.gem +0 -0
  120. data/vendor/cache/coderay-1.0.8.gem +0 -0
  121. data/vendor/cache/diff-lcs-1.1.3.gem +0 -0
  122. data/vendor/cache/escape-0.0.4.gem +0 -0
  123. data/vendor/cache/excon-0.20.1.gem +0 -0
  124. data/vendor/cache/fog-1.8.0.gem +0 -0
  125. data/vendor/cache/formatador-0.2.4.gem +0 -0
  126. data/vendor/cache/guard-1.6.2.gem +0 -0
  127. data/vendor/cache/guard-rspec-2.4.0.gem +0 -0
  128. data/vendor/cache/highline-1.6.18.gem +0 -0
  129. data/vendor/cache/httpclient-2.2.4.gem +0 -0
  130. data/vendor/cache/i18n-0.6.1.gem +0 -0
  131. data/vendor/cache/json_pure-1.6.8.gem +0 -0
  132. data/vendor/cache/listen-0.7.2.gem +0 -0
  133. data/vendor/cache/log4r-1.1.10.gem +0 -0
  134. data/vendor/cache/lumberjack-1.0.2.gem +0 -0
  135. data/vendor/cache/method_source-0.8.1.gem +0 -0
  136. data/vendor/cache/mime-types-1.22.gem +0 -0
  137. data/vendor/cache/multi_json-1.1.0.gem +0 -0
  138. data/vendor/cache/net-scp-1.0.4.gem +0 -0
  139. data/vendor/cache/net-ssh-2.2.2.gem +0 -0
  140. data/vendor/cache/net-ssh-gateway-1.1.0.gem +0 -0
  141. data/vendor/cache/netaddr-1.5.0.gem +0 -0
  142. data/vendor/cache/nokogiri-1.5.9.gem +0 -0
  143. data/vendor/cache/open4-1.3.0.gem +0 -0
  144. data/vendor/cache/progressbar-0.9.2.gem +0 -0
  145. data/vendor/cache/pry-0.9.11.4-java.gem +0 -0
  146. data/vendor/cache/pry-0.9.11.4.gem +0 -0
  147. data/vendor/cache/rake-10.0.3.gem +0 -0
  148. data/vendor/cache/rb-fsevent-0.9.3.gem +0 -0
  149. data/vendor/cache/redcard-1.0.0.gem +0 -0
  150. data/vendor/cache/rspec-2.12.0.gem +0 -0
  151. data/vendor/cache/rspec-core-2.12.2.gem +0 -0
  152. data/vendor/cache/rspec-expectations-2.12.1.gem +0 -0
  153. data/vendor/cache/rspec-mocks-2.12.2.gem +0 -0
  154. data/vendor/cache/ruby-atmos-pure-1.0.5.gem +0 -0
  155. data/vendor/cache/ruby-hmac-0.4.0.gem +0 -0
  156. data/vendor/cache/settingslogic-2.0.9.gem +0 -0
  157. data/vendor/cache/slop-3.4.3.gem +0 -0
  158. data/vendor/cache/spoon-0.0.1.gem +0 -0
  159. data/vendor/cache/terminal-table-1.4.5.gem +0 -0
  160. data/vendor/cache/thor-0.17.0.gem +0 -0
  161. data/vendor/cache/uuidtools-2.1.3.gem +0 -0
  162. data/vendor/cache/xml-simple-1.1.2.gem +0 -0
@@ -1,1347 +0,0 @@
1
- require "thor"
2
- require "highline"
3
- require "fileutils"
4
-
5
- # for the #sh helper
6
- require "rake"
7
- require "rake/file_utils"
8
-
9
- require "escape"
10
-
11
- require "bosh-bootstrap/helpers"
12
-
13
- module Bosh::Bootstrap
14
- class Cli < Thor
15
- include Thor::Actions
16
- include Bosh::Bootstrap::Helpers::FogSetup
17
- include Bosh::Bootstrap::Helpers::Settings
18
- include Bosh::Bootstrap::Helpers::SettingsSetter
19
- include FileUtils
20
-
21
- AWS_JENKINS_BUCKET = "bosh-jenkins-artifacts"
22
-
23
- attr_reader :fog_credentials
24
- attr_reader :server
25
-
26
- desc "deploy", "Bootstrap Micro BOSH, and optionally an Inception VM"
27
- method_option :"edge-prebuilt", :type => :boolean, :desc => "Use AWS us-east-1 gems & prebuilt AMIs"
28
- method_option :"edge", :type => :boolean, :desc => "Use pre-built gems; create microbosh from source [temporary default]"
29
- method_option :fog, :type => :string, :desc => "fog config file (default: ~/.fog)"
30
- method_option :"upgrade-deps", :type => :boolean, :desc => "Force upgrade dependencies, packages & gems"
31
- method_option :"create-inception", :type => :boolean, :desc => "Choose to create an inception VM"
32
- def deploy
33
- migrate_old_settings
34
- load_deploy_options # from method_options above
35
-
36
- deploy_stage_1_choose_infrastructure_provider
37
- load_provider_specific_options
38
-
39
- deploy_stage_2_bosh_configuration
40
- deploy_stage_3_create_allocate_inception_vm
41
- deploy_stage_4_prepare_inception_vm
42
- deploy_stage_5_salted_password
43
- deploy_stage_6_download_micro_bosh
44
- deploy_stage_7_deploy_micro_bosh
45
- deploy_stage_8_setup_new_bosh
46
- end
47
-
48
- desc "upgrade-inception", "Upgrade inception VM with latest packages, gems, security group ports"
49
- method_option :"edge-deployer", :type => :boolean, :desc => "Install bosh deployer from git instead of rubygems"
50
- def upgrade_inception
51
- migrate_old_settings
52
- load_deploy_options # from method_options above
53
-
54
- setup_server
55
- upgrade_inception_stage_1_prepare_inception_vm
56
- end
57
-
58
- # desc "delete", "Delete Micro BOSH"
59
- # method_option :all, :type => :boolean, :desc => "Delete all micro-boshes and inception VM [coming soon]"
60
- # def delete
61
- # delete_stage_1_target_inception_vm
62
- #
63
- # if options[:all]
64
- # error "I'm sorry; the awesome --all flag is not yet implemented"
65
- # delete_all_stage_2_delete_micro_boshes
66
- # delete_all_stage_3_delete_inception_vm
67
- # else
68
- # delete_one_stage_2_delete_micro_bosh
69
- # end
70
- # end
71
- #
72
- desc "ssh [COMMAND]", "Open an ssh session to the inception VM [do nothing if local machine is inception VM]"
73
- long_desc <<-DESC
74
- If a command is supplied, it will be run, otherwise a session will be
75
- opened.
76
- DESC
77
- def ssh(cmd=nil)
78
- migrate_old_settings
79
- run_ssh_command_or_open_tunnel(cmd)
80
- end
81
-
82
- desc "tmux", "Open an ssh (with tmux) session to the inception VM [do nothing if local machine is inception VM]"
83
- long_desc <<-DESC
84
- Opens a connection using ssh and attaches to the most recent tmux session;
85
- giving you persistance across disconnects.
86
- DESC
87
- def tmux
88
- migrate_old_settings
89
- run_ssh_command_or_open_tunnel(["-t", "tmux attach || tmux new-session"])
90
- end
91
-
92
- desc "mosh", "Open an mosh session to the inception VM [do nothing if local machine is inception VM]"
93
- long_desc <<-DESC
94
- Opens a connection using MOSH (http://mosh.mit.edu/); ideal for those with slow or flakey internet connections.
95
- Requires outgoing UDP port 60001 to the Inception VM
96
- DESC
97
- def mosh
98
- migrate_old_settings
99
- open_mosh_session
100
- end
101
-
102
- no_tasks do
103
- DEFAULT_INCEPTION_VOLUME_SIZE = 32 # Gb
104
- DEFAULT_MICROBOSH_VOLUME_SIZE = 16 # Gb
105
-
106
- def deploy_stage_1_choose_infrastructure_provider
107
- settings["git"] ||= {}
108
- settings["git"]["name"] ||= `git config user.name`.strip
109
- settings["git"]["email"] ||= `git config user.email`.strip
110
- if settings["git"]["name"].empty? || settings["git"]["email"].empty?
111
- error "Checking for git identity....Cannot find your git identity. Please set git user.name and user.email before deploying"
112
- end
113
-
114
- header "Stage 1: Choose infrastructure"
115
- unless settings[:fog_credentials]
116
- choose_fog_provider
117
- end
118
-
119
- unless settings[:bosh_cloud_properties]
120
- build_cloud_properties
121
- end
122
- confirm "Using infrastructure provider #{settings.fog_credentials.provider}"
123
-
124
- if aws?
125
- if ENV['VPC']
126
- choose_aws_vpc_or_ec2
127
- end
128
- end
129
-
130
- unless settings[:region_code]
131
- choose_provider_region
132
- end
133
- if region = settings[:region_code]
134
- settings["fog_credentials"]["region"] = region
135
- settings["bosh_cloud_properties"][settings["bosh_provider"]]["region"] = region
136
- settings["bosh_cloud_properties"][settings["bosh_provider"]]["ec2_endpoint"] = "ec2.#{region}.amazonaws.com"
137
- confirm "Using #{settings.fog_credentials.provider} region #{settings.region_code}"
138
- else
139
- confirm "No specific region/data center for #{settings.fog_credentials.provider}"
140
- end
141
-
142
- unless settings["network_label"]
143
- choose_provider_network_label
144
- end
145
- if settings["network_label"]
146
- confirm "Using #{settings.fog_credentials.provider} network labelled #{settings['network_label']}"
147
- end
148
- end
149
-
150
- def deploy_stage_2_bosh_configuration
151
- header "Stage 2: BOSH configuration"
152
- unless settings[:bosh_name]
153
- provider, region = settings.bosh_provider, settings.region_code
154
- if region
155
- default_name = "microbosh-#{provider}-#{region}".gsub(/\W+/, '-')
156
- else
157
- default_name = "microbosh-#{provider}".gsub(/\W+/, '-')
158
- end
159
- bosh_name = hl.ask("Useful name for Micro BOSH? ") { |q| q.default = default_name }
160
- settings[:bosh_name] = bosh_name
161
- save_settings!
162
- end
163
- confirm "Micro BOSH will be named #{settings.bosh_name}"
164
-
165
- unless settings[:bosh_username]
166
- prompt_for_bosh_credentials
167
- end
168
- confirm "After BOSH is created, your username will be #{settings.bosh_username}"
169
-
170
- unless settings[:bosh_resources_cloud_properties]
171
- settings[:bosh_resources_cloud_properties] = bosh_resources_cloud_properties
172
- save_settings!
173
- end
174
- confirm "Micro BOSH instance type will be #{settings[:bosh_resources_cloud_properties]["instance_type"]}"
175
-
176
- unless settings[:bosh]
177
- password = settings.bosh_password # FIXME dual use of password?
178
- settings[:bosh] = {}
179
- settings[:bosh][:password] = password
180
- if openstack?
181
- settings[:bosh][:persistent_disk] = prompt_for_disk_space("Micro BOSH VM", DEFAULT_MICROBOSH_VOLUME_SIZE) * 1024
182
- else
183
- settings[:bosh][:persistent_disk] = DEFAULT_MICROBOSH_VOLUME_SIZE * 1024
184
- end
185
- save_settings!
186
- end
187
- confirm "Micro BOSH persistent disk size will be #{settings.bosh.persistent_disk} Mb"
188
-
189
- unless settings[:bosh]["ip_address"]
190
- if vpc?
191
- settings[:bosh]["ip_address"] = "10.0.0.6"
192
- else
193
- say "Acquiring IP address for micro BOSH..."
194
- ip_address = acquire_ip_address
195
- settings[:bosh]["ip_address"] = ip_address
196
- end
197
- end
198
- unless settings[:bosh]["ip_address"]
199
- error "IP address not available/provided currently"
200
- else
201
- confirm "Micro BOSH will be assigned IP address #{settings[:bosh]['ip_address']}"
202
- end
203
- save_settings!
204
-
205
- if aws? && vpc?
206
- create_complete_vpc(settings.bosh_name, "10.0.0.0/16", "10.0.0.0/24")
207
- end
208
-
209
- unless settings[:bosh_security_group]
210
- security_group_name = settings.bosh_name
211
- create_security_group(security_group_name)
212
- end
213
- ports = settings.bosh_security_group.ports.values
214
- confirm "Micro BOSH protected by security group " +
215
- "named #{settings.bosh_security_group.name}, with ports #{ports}"
216
-
217
- unless settings[:bosh_key_pair]
218
- key_pair_name = settings.bosh_name
219
- create_key_pair(key_pair_name)
220
- end
221
- confirm "Micro BOSH accessible via key pair named #{settings.bosh_key_pair.name}"
222
-
223
- unless settings[:micro_bosh_stemcell_name]
224
- settings[:micro_bosh_stemcell_name] = micro_bosh_stemcell_name
225
- save_settings!
226
- end
227
-
228
- confirm "Micro BOSH will be created with stemcell #{settings.micro_bosh_stemcell_name}"
229
- end
230
-
231
- def deploy_stage_3_create_allocate_inception_vm
232
- header "Stage 3: Create/Allocate the Inception VM"
233
- unless settings["inception"]
234
- hl.choose do |menu|
235
- menu.prompt = "Create or specify an Inception VM: "
236
- if aws? || openstack?
237
- menu.choice("create new inception VM") do
238
- settings["inception"] = {"create_new" => true}
239
- end
240
- end
241
- menu.choice("use an existing Ubuntu server") do
242
- settings["inception"] = {}
243
- settings["inception"]["host"] = \
244
- hl.ask("Host address (IP or domain) to inception VM? ")
245
- settings["inception"]["username"] = \
246
- hl.ask("Username that you have SSH access to? ") {|q| q.default = "ubuntu"}
247
- end
248
- menu.choice("use this server (must be ubuntu & on same network as bosh)") do
249
- # dummy data for settings.inception
250
- settings["inception"] = {}
251
- settings["inception"]["username"] = `whoami`.strip
252
- end
253
- end
254
- end
255
- save_settings!
256
-
257
- if settings["inception"]["create_new"] && !settings["inception"]["host"]
258
- unless settings["inception"]["key_pair"]
259
- create_inception_key_pair
260
- end
261
- recreate_local_ssh_keys_for_inception_vm
262
- create_security_group_for_inception_vm
263
-
264
- aws? ? boot_aws_inception_vm : boot_openstack_inception_vm
265
- end
266
- # If successfully validate inception VM, then save those settings.
267
- save_settings!
268
-
269
- setup_server
270
-
271
- unless settings["inception"]["validated"]
272
- unless run_server(Bosh::Bootstrap::Stages::StageValidateInceptionVm.new(settings).commands)
273
- error "Failed to complete Stage 3: Create/Allocate the Inception VM"
274
- end
275
- settings["inception"]["validated"] = true
276
- end
277
- # If successfully validate inception VM, then save those settings.
278
- save_settings!
279
- end
280
-
281
- def deploy_stage_4_prepare_inception_vm
282
- unless settings["inception"] && settings["inception"]["prepared"] && !settings["upgrade_deps"]
283
- header "Stage 4: Preparing the Inception VM"
284
- recreate_local_ssh_keys_for_inception_vm
285
-
286
- unless run_server(Bosh::Bootstrap::Stages::StagePrepareInceptionVm.new(settings).commands)
287
- error "Failed to complete Stage 4: Preparing the Inception VM"
288
- end
289
- settings["inception"]["prepared"] = true
290
- save_settings!
291
- else
292
- header "Stage 4: Preparing the Inception VM", :skipping => "Already prepared inception VM."
293
- end
294
- end
295
-
296
- def deploy_stage_5_salted_password
297
- unless settings["bosh"] && settings["bosh"]["salted_password"]
298
- header "Stage 5: Generate salted password"
299
- recreate_local_ssh_keys_for_inception_vm
300
-
301
- unless run_server(Bosh::Bootstrap::Stages::SaltedPassword.new(settings).commands)
302
- error "Failed to complete Stage 5: Generate salted password"
303
- end
304
- save_settings!
305
- else
306
- header "Stage 5: Generate salted password", skipping: "Already generated salted password"
307
- end
308
- end
309
-
310
- def deploy_stage_6_download_micro_bosh
311
- header "Stage 6: Download micro BOSH"
312
- recreate_local_ssh_keys_for_inception_vm
313
- switch_to_prebuilt_microbosh_ami_if_available
314
-
315
- unless run_server(Bosh::Bootstrap::Stages::MicroBoshDownload.new(settings).commands)
316
- error "Failed to complete Stage 6: Downloading micro BOSH"
317
- end
318
- # Settings are updated by this stage
319
- # It may update the micro_bosh_stemcell_name
320
- save_settings!
321
-
322
- confirm "Successfully built micro BOSH"
323
- end
324
-
325
- def deploy_stage_7_deploy_micro_bosh
326
- header "Stage 7: Deploying micro BOSH"
327
- recreate_local_ssh_keys_for_inception_vm
328
-
329
- unless run_server(Bosh::Bootstrap::Stages::MicroBoshDeploy.new(settings).commands)
330
- error "Failed to complete Stage 7: Deploying micro BOSH"
331
- end
332
-
333
- confirm "Successfully built micro BOSH"
334
- end
335
-
336
- def deploy_stage_8_setup_new_bosh
337
- # TODO change to a polling test of director being available
338
- say "Pausing to wait for BOSH Director..."
339
- sleep 5
340
-
341
- header "Stage 8: Setup bosh"
342
- unless run_server(Bosh::Bootstrap::Stages::SetupNewBosh.new(settings).commands)
343
- error "Failed to complete Stage 7: Setup bosh"
344
- end
345
-
346
- say "Locally targeting and login to new BOSH..."
347
- sh "bosh -u #{settings.bosh_username} -p #{settings.bosh_password} target #{settings.bosh.ip_address}"
348
- sh "bosh login #{settings.bosh_username} #{settings.bosh_password}"
349
-
350
- save_settings!
351
-
352
- confirm "You are now targeting and logged in to your BOSH"
353
- end
354
-
355
- def upgrade_inception_stage_1_prepare_inception_vm
356
- if settings["inception"] && settings["inception"]["prepared"]
357
- header "Stage 1: Upgrade Inception VM"
358
- unless run_server(Bosh::Bootstrap::Stages::StagePrepareInceptionVm.new(settings).commands)
359
- error "Failed to complete Stage 2: Upgrade Inception VM"
360
- end
361
- else
362
- error "Please deploy an Inception VM first, using 'bosh-bootstrap deploy' command."
363
- end
364
- end
365
-
366
- def delete_stage_1_target_inception_vm
367
- header "Stage 1: Target inception VM to use to delete micro-bosh"
368
- setup_server
369
- end
370
-
371
- def delete_one_stage_2_delete_micro_bosh
372
- header "Stage 2: Deleting micro BOSH"
373
- unless run_server(Bosh::Bootstrap::Stages::MicroBoshDelete.new(settings).commands)
374
- error "Failed to complete Stage 1: Delete micro BOSH"
375
- end
376
- save_settings!
377
- end
378
-
379
- def delete_all_stage_2_delete_micro_boshes
380
-
381
- end
382
-
383
- def delete_all_stage_3_delete_inception_vm
384
-
385
- end
386
-
387
- def setup_server
388
- if settings["inception"]["host"]
389
- private_key_path = settings["inception"]["local_private_key_path"]
390
- @server = Commander::RemoteServer.new(settings.inception.host, private_key_path)
391
- confirm "Using inception VM #{settings.inception.username}@#{settings.inception.host}"
392
- else
393
- @server = Commander::LocalServer.new
394
- confirm "Using this server as the inception VM"
395
- end
396
- end
397
-
398
- def create_complete_vpc(name, vpc_range="10.0.0.0/16", subnet_cidr_block="10.0.0.0/24")
399
- with_setting "vpc" do |setting|
400
- say "Creating VPC '#{name}'..."
401
- setting["id"] = provider.create_vpc(name, vpc_range)
402
- end
403
-
404
- vpc_id = settings["vpc"]["id"]
405
- with_setting "internet_gateway" do |setting|
406
- say "Creating internet gateway..."
407
- setting["id"] = provider.create_internet_gateway(vpc_id)
408
- end
409
-
410
- with_setting "subnet" do |setting|
411
- say "Creating subnet #{subnet_cidr_block}..."
412
- setting["id"] = provider.create_subnet(vpc_id, subnet_cidr_block)
413
- end
414
- end
415
-
416
- def run_ssh_command_or_open_tunnel(cmd)
417
- ensure_inception_vm
418
- ensure_inception_vm_has_launched
419
- recreate_local_ssh_keys_for_inception_vm
420
-
421
- username = "vcap"
422
- host = settings["inception"]["host"]
423
- result = system Escape.shell_command(["ssh", "-i", inception_vm_private_key_path, "#{username}@#{host}", cmd].flatten.compact)
424
- exit result
425
- end
426
-
427
- def ensure_inception_vm
428
- unless settings["inception"]
429
- say "No inception VM being used", :yellow
430
- exit 0
431
- end
432
- end
433
- def ensure_inception_vm_has_launched
434
- unless settings.inception["host"]
435
- exit "Inception VM has not finished launching; run to complete: #{self.class.banner_base} deploy"
436
- end
437
- end
438
-
439
- def open_mosh_session
440
- ensure_mosh_installed
441
- ensure_inception_vm
442
- ensure_inception_vm_has_launched
443
- recreate_local_ssh_keys_for_inception_vm
444
- ensure_security_group_allows_mosh
445
-
446
- username = 'vcap'
447
- host = settings.inception[:host]
448
- exit system Escape.shell_command(['mosh', "#{username}@#{host}"])
449
- end
450
-
451
- def ensure_mosh_installed
452
- system 'mosh --version'
453
- unless $?.exitstatus == 255 #mosh --version returns exit code 255, rather than 0 as one might expect. Grrr.
454
- say "You must have MOSH installed to use this command. See http://mosh.mit.edu/#getting", :yellow
455
- exit 0
456
- end
457
- end
458
-
459
- def ensure_security_group_allows_mosh
460
- ports = {
461
- mosh: {
462
- protocol: "udp",
463
- ports: (60000..60050)
464
- }
465
- }
466
- inception_server = fog_compute.servers.get(settings["inception"]["server_id"])
467
- security_group_name = inception_server.groups.first
468
-
469
- say "Ensuring #{ports[:mosh][:protocol]} ports #{ports[:mosh][:ports].to_s} are open", [:yellow, :bold]
470
- say "on Inception VM's security group (#{security_group_name}) ...", [:yellow, :bold]
471
-
472
- #TODO - remove this guard once the other providers have been extended
473
- unless settings['bosh_provider'] == 'aws'
474
- say "TODO: Non-AWS providers need to be extended to allow creation of UDP ports (60000..60050) in their security groups", :yellow
475
- exit 0
476
- end
477
-
478
- provider.create_security_group(security_group_name, 'not used', ports)
479
- end
480
-
481
- # Display header for a new section of the bootstrapper
482
- def header(title, options={})
483
- say "" # golden whitespace
484
- if skipping = options[:skipping]
485
- say "Skipping #{title}", [:yellow, :bold]
486
- say skipping
487
- else
488
- say title, [:green, :bold]
489
- end
490
- say "" # more golden whitespace
491
- end
492
-
493
- def error(message)
494
- say message, :red
495
- exit 1
496
- end
497
-
498
- def confirm(message)
499
- say "Confirming: #{message}", green
500
- say "" # bonus golden whitespace
501
- end
502
-
503
- def load_deploy_options
504
- settings["fog_path"] = File.expand_path(options[:fog] || "~/.fog")
505
-
506
- prompt_git_user_information
507
-
508
- # once a stemcell is downloaded or created; these fields above should
509
- # be uploaded with values such as:
510
- # -> settings["micro_bosh_stemcell_name"] = "micro-bosh-stemcell-aws-0.8.1.tgz"
511
-
512
- if options["upgrade-deps"]
513
- settings["upgrade_deps"] = options["upgrade-deps"]
514
- else
515
- settings.delete("upgrade_deps")
516
- end
517
-
518
- if options["create-inception"]
519
- settings["inception"] = {"create_new" => true}
520
- end
521
- save_settings!
522
- end
523
-
524
- def load_provider_specific_options
525
- # before deploy stage - need to change type => ami if AWS us-east-1?
526
- if options[:"edge-prebuilt"] || settings.delete("edge-prebuilt")
527
- settings["micro_bosh_stemcell_type"] = "edge-prebuilt"
528
- settings["micro_bosh_stemcell_name"] = "edge-prebuilt"
529
- elsif options[:"edge"] || settings.delete("edge")
530
- settings["micro_bosh_stemcell_type"] = "custom"
531
- settings["micro_bosh_stemcell_name"] = "custom"
532
- else
533
- # currently defaulting to latest prebuilt stemcells/amis until 1.5.0 is released
534
- settings["micro_bosh_stemcell_type"] = "edge-prebuilt"
535
- settings["micro_bosh_stemcell_name"] = "edge-prebuilt"
536
- end
537
- end
538
-
539
- def prompt_git_user_information
540
- settings["git"] ||= {}
541
- settings["git"]["name"] ||= `git config user.name`.strip
542
- while settings["git"]["name"].empty?
543
- settings["git"]["name"] = hl.ask("What is your name? (to setup git on inception VM) ")
544
- end
545
- settings["git"]["email"] ||= `git config user.email`.strip
546
- while settings["git"]["email"].empty?
547
- settings["git"]["email"] = hl.ask("What is your email? (to setup git on inception VM) ")
548
- end
549
- end
550
-
551
- # Displays a prompt for known IaaS that are configured
552
- # within .fog config file.
553
- #
554
- # For example:
555
- #
556
- # 1. AWS (default)
557
- # 2. AWS (bosh)
558
- # 3. Alternate credentials
559
- # Choose infrastructure: 1
560
- #
561
- # If .fog config only contains one provider, do not prompt.
562
- #
563
- # fog config file looks like:
564
- # :default:
565
- # :aws_access_key_id: PERSONAL_ACCESS_KEY
566
- # :aws_secret_access_key: PERSONAL_SECRET
567
- # :bosh:
568
- # :aws_access_key_id: SPECIAL_IAM_ACCESS_KEY
569
- # :aws_secret_access_key: SPECIAL_IAM_SECRET_KEY
570
- #
571
- # Convert this into:
572
- # { "AWS (default)" => {:aws_access_key_id => ...}, "AWS (bosh)" => {...} }
573
- #
574
- # Then display options to user to choose.
575
- #
576
- # Currently detects following fog providers:
577
- # * AWS
578
- # * OpenStack
579
- #
580
- # If "Alternate credentials" is selected, then user is prompted for fog
581
- # credentials:
582
- # * provider?
583
- # * access keys?
584
- # * API URI or region?
585
- #
586
- # At the end, settings.fog_credentials contains the credentials for target IaaS
587
- # and :provider key for the IaaS name.
588
- #
589
- # {:provider=>"AWS",
590
- # :aws_access_key_id=>"PERSONAL_ACCESS_KEY",
591
- # :aws_secret_access_key=>"PERSONAL_SECRET"}
592
- #
593
- # settings.fog_credentials.provider is the provider name
594
- # settings.bosh_provider is the BOSH name for the provider (aws,vsphere,openstack)
595
- # so as to local stemcells (see +micro_bosh_stemcell_name+)
596
- def choose_fog_provider
597
- @fog_providers = {}
598
- # Prepare menu options:
599
- # each provider/profile name gets a menu choice option
600
- fog_config.inject({}) do |iaas_options, fog_profile|
601
- profile_name, profile = fog_profile
602
- if profile[:aws_access_key_id]
603
- # TODO does fog have inbuilt detection algorithm?
604
- @fog_providers["AWS (#{profile_name})"] = {
605
- "provider" => "AWS",
606
- "aws_access_key_id" => profile[:aws_access_key_id],
607
- "aws_secret_access_key" => profile[:aws_secret_access_key]
608
- }
609
- end
610
- if profile[:openstack_username]
611
- # TODO does fog have inbuilt detection algorithm?
612
- @fog_providers["OpenStack (#{profile_name})"] = {
613
- "provider" => "OpenStack",
614
- "openstack_username" => profile[:openstack_username],
615
- "openstack_api_key" => profile[:openstack_api_key],
616
- "openstack_tenant" => profile[:openstack_tenant],
617
- "openstack_auth_url" => profile[:openstack_auth_url],
618
- "openstack_region" => profile[:openstack_region]
619
- }
620
- end
621
- end
622
- # Display menu
623
- # Include "Alternate credentials" as the last option
624
- if @fog_providers.keys.size > 0
625
- hl.choose do |menu|
626
- menu.prompt = "Choose infrastructure: "
627
- @fog_providers.each do |label, credentials|
628
- menu.choice(label) { @fog_credentials = credentials }
629
- end
630
- menu.choice("Alternate credentials") { prompt_for_alternate_fog_credentials }
631
- end
632
- else
633
- prompt_for_alternate_fog_credentials
634
- end
635
- settings[:fog_credentials] = {}
636
- @fog_credentials.each do |key, value|
637
- settings[:fog_credentials][key] = value
638
- end
639
- save_settings!
640
- end
641
-
642
- def build_cloud_properties
643
- setup_bosh_cloud_properties
644
- settings[:bosh_provider] = settings.bosh_cloud_properties.keys.first # aws, vsphere...
645
- save_settings!
646
- end
647
-
648
- # If no .fog file is found, or if user chooses "Alternate credentials",
649
- # then this method prompts the user:
650
- # * provider?
651
- # * access keys?
652
- # * API URI or region?
653
- #
654
- # Populates +@fog_credentials+ with a Hash that includes :provider key
655
- # For example:
656
- # {
657
- # :provider => "AWS",
658
- # :aws_access_key_id => ACCESS_KEY,
659
- # :aws_secret_access_key => SECRET_KEY
660
- # }
661
- def prompt_for_alternate_fog_credentials
662
- say "" # glorious whitespace
663
- creds = {}
664
- hl.choose do |menu|
665
- menu.prompt = "Choose infrastructure: "
666
- menu.choice("AWS") do
667
- creds[:provider] = "AWS"
668
- creds[:aws_access_key_id] = hl.ask("Access key: ")
669
- creds[:aws_secret_access_key] = hl.ask("Secret key: ")
670
- end
671
- menu.choice("OpenStack") do
672
- creds[:provider] = "OpenStack"
673
- creds[:openstack_username] = hl.ask("Username: ")
674
- creds[:openstack_api_key] = hl.ask("Password: ")
675
- creds[:openstack_tenant] = hl.ask("Tenant: ")
676
- creds[:openstack_auth_url] = hl.ask("Authorization Token URL: ")
677
- end
678
- end
679
- @fog_credentials = creds
680
- end
681
-
682
- def setup_bosh_cloud_properties
683
- if aws?
684
- settings[:bosh_cloud_properties] = {}
685
- settings[:bosh_cloud_properties][:aws] = {}
686
- props = settings[:bosh_cloud_properties][:aws]
687
- props[:access_key_id] = settings.fog_credentials.aws_access_key_id
688
- props[:secret_access_key] = settings.fog_credentials.aws_secret_access_key
689
- # props[:ec2_endpoint] = "ec2.REGION.amazonaws.com" - via +choose_aws_region+
690
- # props[:region] = REGION - via +choose_aws_region+
691
- # props[:default_key_name] = "microbosh" - via +create_aws_key_pair+
692
- # props[:ec2_private_key] = "/home/vcap/.ssh/microbosh.pem" - via +create_aws_key_pair+
693
- # props[:default_security_groups] = ["microbosh"], - via +create_aws_security_group+
694
- elsif openstack?
695
- settings[:bosh_cloud_properties] = {}
696
- settings[:bosh_cloud_properties][:openstack] = {}
697
- props = settings[:bosh_cloud_properties][:openstack]
698
- props[:username] = settings.fog_credentials.openstack_username
699
- props[:api_key] = settings.fog_credentials.openstack_api_key
700
- props[:tenant] = settings.fog_credentials.openstack_tenant
701
- props[:auth_url] = settings.fog_credentials.openstack_auth_url
702
- # props[:default_key_name] = "microbosh" - via +create_openstack_key_pair+
703
- # props[:private_key] = "/home/vcap/.ssh/microbosh.pem" - via +create_openstack_key_pair+
704
- # props[:default_security_groups] = ["microbosh"], - via +create_openstack_security_group+
705
- else
706
- raise "implement #bosh_cloud_properties for #{settings.fog_credentials.provider}"
707
- end
708
- end
709
-
710
- def bosh_resources_cloud_properties
711
- if aws?
712
- {"instance_type" => "m1.medium"}
713
- elsif openstack?
714
- {"instance_type" => choose_bosh_openstack_flavor}
715
- else
716
- raise "implement #bosh_resources_cloud_properties for #{settings.fog_credentials.provider}"
717
- end
718
- end
719
-
720
- def choose_bosh_openstack_flavor
721
- say ""
722
- hl.choose do |menu|
723
- menu.prompt = "Choose Micro BOSH instance type: "
724
- fog_compute.flavors.each do |flavor|
725
- menu.choice(flavor.name) do
726
- return flavor.name
727
- end
728
- end
729
- end
730
- end
731
-
732
- # Ask user to provide region information (URI)
733
- # or choose from a known list of regions (e.g. AWS)
734
- # Return true if region selected (@region_code is set)
735
- # Else return false
736
- def choose_provider_region
737
- if aws?
738
- choose_aws_region
739
- else
740
- return false if settings.has_key?("region_code")
741
- prompt_openstack_region
742
- end
743
- end
744
-
745
- def choose_aws_vpc_or_ec2
746
- if settings["use_vpc"].nil?
747
- settings["use_vpc"] = begin
748
- answer = hl.ask("You want to use VPC, right? ") {|q| q.default="yes"; q.validate = /(yes|no)/i }.match(/y/)
749
- !!answer
750
- end
751
- save_settings!
752
- end
753
- end
754
-
755
- def choose_aws_region
756
- aws_regions = provider.region_labels
757
- default_aws_region = provider.default_region_label
758
-
759
- hl.choose do |menu|
760
- menu.prompt = "Choose AWS region (default: #{default_aws_region}): "
761
- aws_regions.each do |region|
762
- menu.choice(region) do
763
- settings["region_code"] = region
764
- save_settings!
765
- end
766
- menu.default = default_aws_region
767
- end
768
- end
769
- reset_fog_compute
770
- true
771
- end
772
-
773
- def prompt_openstack_region
774
- default_region = settings["fog_credentials"] && settings["fog_credentials"]["openstack_region"]
775
- region = hl.ask("OpenStack Region (optional): ") { |q| q.default = default_region }
776
- settings[:region_code] = region.strip == "" ? nil : region
777
- return false unless settings[:region_code]
778
-
779
- settings["fog_credentials"]["openstack_region"] = settings[:region_code]
780
- settings["bosh_cloud_properties"]["openstack"]["region"] = settings[:region_code]
781
- save_settings!
782
- reset_fog_compute
783
- true
784
- end
785
-
786
- def choose_provider_network_label
787
- if openstack?
788
- prompt_openstack_network_label
789
- end
790
- end
791
-
792
- def prompt_openstack_network_label
793
- settings[:network_label] = hl.ask("OpenStack private network label: ") { |q| q.default = "private" }
794
- end
795
-
796
- # Creates a security group.
797
- # Also sets up the bosh_cloud_properties for the remote server
798
- #
799
- # Adds settings:
800
- # * bosh_security_group.name
801
- # * bosh_security_group.ports
802
- # * bosh_cloud_properties.<bosh_provider>.default_security_groups
803
- def create_security_group(security_group_name)
804
- ports = {
805
- ssh_access: 22,
806
- nats_server: 4222,
807
- message_bus: 6868,
808
- blobstore: 25250,
809
- bosh_director: 25555,
810
- bosh_registry: 25777
811
- }
812
- # TODO: New stemcells to be released will use 25777, so this can be deleted
813
- ports[:openstack_registry] = 25889 if openstack?
814
-
815
- provider.create_security_group(security_group_name, "microbosh", ports)
816
-
817
- settings["bosh_cloud_properties"][provider_name]["default_security_groups"] = [security_group_name]
818
- settings["bosh_security_group"] = {}
819
- settings["bosh_security_group"]["name"] = security_group_name
820
- settings["bosh_security_group"]["ports"] = {}
821
- ports.each { |name, port| settings["bosh_security_group"]["ports"][name.to_s] = port }
822
- save_settings!
823
- end
824
-
825
- # Creates a security group for the inception VM allowing SSH access & ICMP traffic
826
- #
827
- # Adds settings:
828
- # * inception.security_group
829
- def create_security_group_for_inception_vm
830
-
831
- return if settings["inception"]["security_group"]
832
-
833
- ports = {
834
- ssh_access: 22,
835
- ping: { protocol: "icmp", ports: (-1..-1) }
836
- }
837
- security_group_name = "#{settings.bosh_name}-inception-vm"
838
-
839
- provider.create_security_group(security_group_name, "inception-vm", ports)
840
-
841
- settings["inception"] ||= {}
842
- settings["inception"]["security_group"] = security_group_name
843
- save_settings!
844
- end
845
-
846
- # Creates a key pair, and stores the private key in settings manifest.
847
- # Also sets up the bosh_cloud_properties for the remote server
848
- # to have the .pem key installed.
849
- #
850
- # Adds settings:
851
- # * bosh_key_pair.name
852
- # * bosh_key_pair.private_key
853
- # * bosh_key_pair.fingerprint
854
- # For AWS:
855
- # * bosh_cloud_properties.aws.default_key_name
856
- # * bosh_cloud_properties.aws.ec2_private_key
857
- # For OpenStack:
858
- # * bosh_cloud_properties.openstack.default_key_name
859
- # * bosh_cloud_properties.openstack.private_key
860
- def create_key_pair(key_pair_name)
861
- unless fog_compute.key_pairs.get(key_pair_name)
862
- say "creating key pair #{key_pair_name}..."
863
- kp = provider.create_key_pair(key_pair_name)
864
- settings[:bosh_key_pair] = {}
865
- settings[:bosh_key_pair][:name] = key_pair_name
866
- settings[:bosh_key_pair][:private_key] = kp.private_key
867
- settings[:bosh_key_pair][:fingerprint] = kp.fingerprint
868
- if aws?
869
- settings["bosh_cloud_properties"]["aws"]["default_key_name"] = key_pair_name
870
- settings["bosh_cloud_properties"]["aws"]["ec2_private_key"] = "/home/vcap/.ssh/#{key_pair_name}.pem"
871
- elsif openstack?
872
- settings["bosh_cloud_properties"]["openstack"]["default_key_name"] = key_pair_name
873
- settings["bosh_cloud_properties"]["openstack"]["private_key"] = "/home/vcap/.ssh/#{key_pair_name}.pem"
874
- end
875
- save_settings!
876
- else
877
- error "Key pair '#{key_pair_name}' already exists. Rename BOSH or delete old key pair manually and re-run CLI."
878
- end
879
- end
880
-
881
- # Creates a key pair with the provider for the inception VM.
882
- # Stores the private & public key in settings manifest.
883
- #
884
- # If provider already has a key pair of the same name, it re-creates it.
885
- #
886
- # Adds settings:
887
- # * inception.key_pair.name
888
- # * inception.key_pair.public_key
889
- # * inception.key_pair.private_key
890
- # * inception.key_pair.fingerprint
891
- def create_inception_key_pair
892
- say "Creating ssh key pair for Inception VM..."
893
- create_key_pair_store_in_settings("inception")
894
- end
895
-
896
- # Creates a key pair with the provider.
897
- # Stores the private & public key in settings manifest.
898
- #
899
- # If provider already has a key pair of the same name, it re-creates it.
900
- #
901
- # Adds settings:
902
- # * <settings_key>.key_pair.name # defaults to settings_key value
903
- # * <settings_key>.key_pair.public_key
904
- # * <settings_key>.key_pair.private_key
905
- # * <settings_key>.key_pair.fingerprint
906
- def create_key_pair_store_in_settings(settings_key, default_key_pair_name = settings_key)
907
- settings[settings_key] ||= {}
908
- settings[settings_key]["key_pair"] ||= {}
909
- key_pair_settings = settings[settings_key]["key_pair"]
910
- key_pair_settings["name"] ||= default_key_pair_name
911
- key_pair_name = key_pair_settings["name"]
912
-
913
- provider.delete_key_pair_if_exists(key_pair_name)
914
- fog_key_pair = provider.create_key_pair(key_pair_name)
915
-
916
- key_pair_settings["private_key"] = fog_key_pair.private_key
917
- key_pair_settings["public_key"] = fog_key_pair.public_key
918
- key_pair_settings["fingerprint"] = fog_key_pair.fingerprint
919
- save_settings!
920
- end
921
-
922
- # Provisions an AWS m1.small VM as the inception VM
923
- # Updates settings.inception.host/username
924
- #
925
- # NOTE: if any stage fails, when the CLI is re-run
926
- # and "create new server" is selected again, the process should
927
- # complete
928
- def boot_aws_inception_vm
929
- say "" # glowing whitespace
930
-
931
- unless settings["inception"]["ip_address"]
932
- say "Provisioning IP address for inception VM..."
933
- settings["inception"]["ip_address"] = acquire_ip_address
934
- save_settings!
935
- end
936
-
937
- unless settings["inception"] && settings["inception"]["server_id"]
938
- username = "ubuntu"
939
- size = "m1.small"
940
- ip_address = settings["inception"]["ip_address"]
941
- key_name = settings["inception"]["key_pair"]["name"]
942
- say "Provisioning #{size} for inception VM..."
943
- inception_vm_attributes = {
944
- :groups => [settings["inception"]["security_group"]],
945
- :key_name => key_name,
946
- :private_key_path => inception_vm_private_key_path,
947
- :flavor_id => size,
948
- :bits => 64,
949
- :username => "ubuntu",
950
- :public_ip_address => ip_address
951
- }
952
- if vpc?
953
- raise "must create subnet before creating VPC inception VM" unless settings["subnet"] && settings["subnet"]["id"]
954
- inception_vm_attributes[:subnet_id] = settings["subnet"]["id"]
955
- inception_vm_attributes[:private_ip_address] = "10.0.0.5"
956
- end
957
- server = provider.bootstrap(inception_vm_attributes)
958
- unless server
959
- error "Something mysteriously cloudy happened and fog could not provision a VM. Please check your limits."
960
- end
961
-
962
- settings["inception"].delete("create_new")
963
- settings["inception"]["server_id"] = server.id
964
- settings["inception"]["username"] = username
965
- save_settings!
966
- end
967
-
968
- server ||= fog_compute.servers.get(settings["inception"]["server_id"])
969
-
970
- unless settings["inception"]["disk_size"]
971
- disk_size = DEFAULT_INCEPTION_VOLUME_SIZE # Gb
972
- device = "/dev/sdi"
973
- provision_and_mount_volume(server, disk_size, device)
974
-
975
- settings["inception"]["disk_size"] = disk_size
976
- settings["inception"]["disk_device"] = device
977
- save_settings!
978
- end
979
-
980
- # settings["inception"]["host"] is used externally to determine
981
- # if an inception VM has been assigned already; so we leave it
982
- # until last in this method to set this setting.
983
- # This way we can always rerun the CLI and rerun this method
984
- # and idempotently get an inception VM
985
- unless settings["inception"]["host"]
986
- settings["inception"]["host"] = server.dns_name
987
- save_settings!
988
- end
989
-
990
- confirm "Inception VM has been created"
991
- display_inception_ssh_access
992
- end
993
-
994
- # Provisions an OpenStack m1.small VM as the inception VM
995
- # Updates settings.inception.host/username
996
- #
997
- # NOTE: if any stage fails, when the CLI is re-run
998
- # and "create new server" is selected again, the process should
999
- # complete
1000
- def boot_openstack_inception_vm
1001
- say "" # glowing whitespace
1002
-
1003
- unless settings["inception"] && settings["inception"]["server_id"]
1004
- username = "ubuntu"
1005
- say "Provisioning server for inception VM..."
1006
- settings["inception"] ||= {}
1007
-
1008
- # Select OpenStack flavor
1009
- if settings["inception"]["flavor_id"]
1010
- inception_flavor = fog_compute.flavors.find { |f| f.id == settings["inception"]["flavor_id"] }
1011
- settings["inception"]["flavor_id"] = nil if inception_flavor.nil?
1012
- end
1013
- unless settings["inception"]["flavor_id"]
1014
- say ""
1015
- hl.choose do |menu|
1016
- menu.prompt = "Choose OpenStack flavor: "
1017
- fog_compute.flavors.each do |flavor|
1018
- menu.choice(flavor.name) do
1019
- inception_flavor = flavor
1020
- settings["inception"]["flavor_id"] = inception_flavor.id
1021
- save_settings!
1022
- end
1023
- end
1024
- end
1025
- end
1026
- say ""
1027
- confirm "Using flavor #{inception_flavor.name} for Inception VM"
1028
-
1029
- # Select OpenStack image
1030
- if settings["inception"]["image_id"]
1031
- inception_image = fog_compute.images.find { |i| i.id == settings["inception"]["image_id"] }
1032
- settings["inception"]["image_id"] = nil if inception_image.nil?
1033
- end
1034
- unless settings["inception"]["image_id"]
1035
- say ""
1036
- hl.choose do |menu|
1037
- menu.prompt = "Choose OpenStack image (Ubuntu): "
1038
- fog_compute.images.each do |image|
1039
- menu.choice(image.name) do
1040
- inception_image = image
1041
- settings["inception"]["image_id"] = inception_image.id
1042
- save_settings!
1043
- end
1044
- end
1045
- end
1046
- end
1047
- say ""
1048
- confirm "Using image #{inception_image.name} for Inception VM"
1049
-
1050
- key_name = settings["inception"]["key_pair"]["name"]
1051
-
1052
- # Boot OpenStack server
1053
- server = fog_compute.servers.create(
1054
- :name => "Inception VM",
1055
- :key_name => key_name,
1056
- :private_key_path => inception_vm_private_key_path,
1057
- :flavor_ref => inception_flavor.id,
1058
- :image_ref => inception_image.id,
1059
- :security_groups => [settings["inception"]["security_group"]],
1060
- :username => username
1061
- )
1062
- server.wait_for { ready? }
1063
- unless server
1064
- error "Something mysteriously cloudy happened and fog could not provision a VM. Please check your limits."
1065
- end
1066
-
1067
- settings["inception"].delete("create_new")
1068
- settings["inception"]["server_id"] = server.id
1069
- settings["inception"]["username"] = username
1070
- save_settings!
1071
- end
1072
-
1073
- server ||= fog_compute.servers.get(settings["inception"]["server_id"])
1074
-
1075
- unless settings["inception"]["ip_address"]
1076
- say "Provisioning IP address for inception VM..."
1077
- ip_address = acquire_ip_address
1078
- associate_ip_address_with_server(ip_address, server)
1079
-
1080
- settings["inception"]["ip_address"] = ip_address
1081
- save_settings!
1082
- end
1083
-
1084
- # TODO: Hack
1085
- unless server.public_ip_address
1086
- server.addresses["public"] = [settings["inception"]["ip_address"]]
1087
- end
1088
- unless server.private_key_path
1089
- server.private_key_path = inception_vm_private_key_path
1090
- end
1091
- server.username = settings["inception"]["username"]
1092
- Fog.wait_for(60) { server.sshable? }
1093
-
1094
- unless settings["inception"]["disk_size"]
1095
- disk_size = prompt_for_disk_space("Inception VM", DEFAULT_INCEPTION_VOLUME_SIZE)
1096
- device = "/dev/vdc"
1097
- provision_and_mount_volume(server, disk_size, device)
1098
-
1099
- settings["inception"]["disk_size"] = disk_size
1100
- settings["inception"]["disk_device"] = device
1101
- save_settings!
1102
- end
1103
-
1104
- # settings["inception"]["host"] is used externally to determine
1105
- # if an inception VM has been assigned already; so we leave it
1106
- # until last in this method to set this setting.
1107
- # This way we can always rerun the CLI and rerun this method
1108
- # and idempotently get an inception VM
1109
- unless settings["inception"]["host"]
1110
- settings["inception"]["host"] = settings["inception"]["ip_address"]
1111
- save_settings!
1112
- end
1113
-
1114
- confirm "Inception VM has been created"
1115
- display_inception_ssh_access
1116
- end
1117
-
1118
- # Provision or provide an IP address to use
1119
- # For AWS, it will dynamically provision an elastic IP
1120
- # For OpenStack, it will dynamically provision a floating IP
1121
- def acquire_ip_address
1122
- unless public_ip = provider.provision_public_ip_address(vpc: vpc?)
1123
- say "Unable to acquire a public IP. Please check your account for capacity or service issues.".red
1124
- exit 1
1125
- end
1126
- public_ip
1127
- end
1128
-
1129
- def associate_ip_address_with_server(ip_address, server)
1130
- provider.associate_ip_address_with_server(ip_address, server)
1131
- server.reload
1132
- end
1133
-
1134
- def prompt_for_disk_space(disk_for, default_size = nil)
1135
- hl.ask("Size of disk for #{disk_for} (in Gb): ", Integer) do |q|
1136
- q.default = default_size if default_size
1137
- q.in = 1..1024
1138
- end
1139
- end
1140
-
1141
- # Provision a volume for a specific device (unless already provisioned)
1142
- # Request that the +server+ mount the volume at the +device+ location.
1143
- #
1144
- # Requires that we can SSH into +server+.
1145
- def provision_and_mount_volume(server, disk_size, device)
1146
- unless provider.find_server_device(server, device)
1147
- say "Provisioning #{disk_size}Gb persistent disk for inception VM..."
1148
- provider.create_and_attach_volume("Inception Disk", disk_size, server, device)
1149
- end
1150
-
1151
- # Format and mount the volume
1152
- # if aws?
1153
- # say "Skipping volume mounting on AWS 12.10 inception VM until its fixed", [:yellow, :bold]
1154
- # run_ssh_command_until_successful server, "sudo mkdir -p /var/vcap/store"
1155
- # else
1156
- say "Mounting persistent disk as volume on inception VM..."
1157
- run_ssh_command_until_successful server, "sudo mkfs.ext4 #{device} -F"
1158
- run_ssh_command_until_successful server, "sudo mkdir -p /var/vcap/store"
1159
- run_ssh_command_until_successful server, "sudo mount #{device} /var/vcap/store"
1160
- # end
1161
- end
1162
-
1163
- def run_ssh_command_until_successful(server, cmd)
1164
- completed = false
1165
- until completed
1166
- begin
1167
- say "Running on inception VM: #{cmd}"
1168
- result = server.ssh([cmd]).first
1169
- if result.status == 1
1170
- result.display_stdout
1171
- result.display_stderr
1172
- sleep 1
1173
- say "trying again..."
1174
- next
1175
- else
1176
- end
1177
- completed = true
1178
- rescue Errno::ETIMEDOUT => e
1179
- say "Timeout error/warning mounting volume, retrying...", yellow
1180
- end
1181
- end
1182
- end
1183
-
1184
- def display_inception_ssh_access
1185
- say "SSH access: ssh -i #{inception_vm_private_key_path} #{settings["inception"]["username"]}@#{settings["inception"]["host"]}"
1186
- end
1187
-
1188
- def run_server(server_commands)
1189
- server.run(server_commands)
1190
- end
1191
-
1192
- def inception_vm_private_key_path
1193
- unless settings["inception"] && settings["inception"]["local_private_key_path"]
1194
- settings["inception"] ||= {}
1195
- settings["inception"]["local_private_key_path"] = File.join(settings_ssh_dir, "inception")
1196
- save_settings!
1197
- end
1198
- settings["inception"]["local_private_key_path"]
1199
- end
1200
-
1201
- # The keys for the inception VM originate from the provider and are cached in
1202
- # the manifest. The private key is stored locally; the public key is placed
1203
- # on the inception VM.
1204
- def recreate_local_ssh_keys_for_inception_vm
1205
- unless settings["inception"] && (key_pair = settings["inception"]["key_pair"])
1206
- raise "please run create_inception_key_pair first"
1207
- end
1208
- private_key_contents = key_pair["private_key"]
1209
- unless File.exist?(inception_vm_private_key_path) && File.read(inception_vm_private_key_path) == private_key_contents
1210
- say "Creating missing inception VM private key..."
1211
- mkdir_p(File.dirname(inception_vm_private_key_path))
1212
- File.chmod(0700, File.dirname(inception_vm_private_key_path))
1213
- File.open(inception_vm_private_key_path, "w") { |file| file << private_key_contents }
1214
- File.chmod(0600, inception_vm_private_key_path)
1215
- end
1216
- end
1217
-
1218
- def aws?
1219
- (settings["fog_credentials"] && settings["fog_credentials"]["provider"] == "AWS") ||
1220
- (settings["bosh_provider"] == "aws")
1221
- end
1222
-
1223
- def vpc?
1224
- settings["use_vpc"]
1225
- end
1226
-
1227
- def openstack?
1228
- (settings["fog_credentials"] && settings["fog_credentials"]["provider"] == "OpenStack") ||
1229
- (settings["bosh_provider"] == "openstack")
1230
- end
1231
-
1232
- def prompt_for_bosh_credentials
1233
- say "Please enter a user/password for the BOSH that will be created."
1234
- prompt = hl
1235
- password_confirmation = nil
1236
- settings[:bosh_username] = prompt.ask("BOSH username: ") { |q| q.default = `whoami`.strip }
1237
- while password_confirmation.nil? || settings[:bosh_password] == "" || settings[:bosh_password] != password_confirmation
1238
- settings[:bosh_password] = prompt.ask("BOSH password: ") { |q| q.echo = "x" }
1239
- if settings[:bosh_password] == ""
1240
- say "Please enter a password"
1241
- next
1242
- end
1243
- password_confirmation = prompt.ask("Confirm BOSH password: ") { |q| q.echo = "x" }
1244
- unless settings[:bosh_password] == password_confirmation
1245
- say "Password do not match. Try Again"
1246
- password_confirmation = nil
1247
- end
1248
- end
1249
-
1250
- save_settings!
1251
- end
1252
-
1253
- # Returns the latest micro-bosh stemcell
1254
- # for the target provider (aws, vsphere, openstack)
1255
- # The name includes the version number.
1256
- def micro_bosh_stemcell_name
1257
- hypersivor = openstack? ? "-kvm" : ""
1258
- @micro_bosh_stemcell_name ||= "micro-bosh-stemcell-#{provider_name}#{hypersivor}-#{known_stable_micro_bosh_stemcell_version}.tgz"
1259
- end
1260
-
1261
- def known_stable_micro_bosh_stemcell_version
1262
- "0.8.1"
1263
- end
1264
-
1265
- def switch_to_prebuilt_microbosh_ami_if_available
1266
- if ami = latest_prebuilt_microbosh_ami
1267
- say "Switching to using prebuilt AMI for bonus speed!", :green
1268
- settings["micro_bosh_stemcell_type"] = "ami"
1269
- settings["micro_bosh_stemcell_name"] = ami
1270
- save_settings!
1271
- end
1272
- end
1273
-
1274
- # return the latest prebuilt microbosh AMI if it is available for target region
1275
- def latest_prebuilt_microbosh_ami
1276
- if aws? && settings["region_code"] == "us-east-1"
1277
- Net::HTTP.get("#{AWS_JENKINS_BUCKET}.s3.amazonaws.com", "/last_successful_micro-bosh-stemcell_ami").strip
1278
- else
1279
- nil
1280
- end
1281
- end
1282
-
1283
- def latest_micro_bosh_stemcell_name
1284
- stemcell_filter_tags = ['micro', provider_name]
1285
- if settings["micro_bosh_stemcell_type"] == "stable"
1286
- unless openstack?
1287
- # FIXME remove this if when openstack has its first stable
1288
- stemcell_filter_tags << "stable" # latest stable micro-bosh stemcell by default
1289
- end
1290
- end
1291
- tags = stemcell_filter_tags.join(",")
1292
- bosh_stemcells_cmd = "bosh public stemcells --tags #{tags}"
1293
- say "Locating micro-bosh stemcell, running '#{bosh_stemcells_cmd}'..."
1294
- #
1295
- # The +bosh_stemcells_cmd+ has an output that looks like:
1296
- # +--------------------------------------------------+-----------------------------+
1297
- # | Name | Tags |
1298
- # +--------------------------------------------------+-----------------------------+
1299
- # | micro-bosh-stemcell-aws-0.6.4.tgz | aws, micro, stable |
1300
- # | micro-bosh-stemcell-aws-0.7.0.tgz | aws, micro, test |
1301
- # | micro-bosh-stemcell-aws-0.8.1.tgz | aws, micro, test |
1302
- # | micro-bosh-stemcell-aws-1.5.0.pre1.tgz | aws, micro |
1303
- # | micro-bosh-stemcell-aws-1.5.0.pre2.tgz | aws, micro |
1304
- # | micro-bosh-stemcell-openstack-0.7.0.tgz | openstack, micro, test |
1305
- # | micro-bosh-stemcell-openstack-kvm-0.8.1.tgz | openstack, kvm, micro, test |
1306
- # | micro-bosh-stemcell-openstack-kvm-1.5.0.pre1.tgz | openstack, kvm, micro |
1307
- # | micro-bosh-stemcell-openstack-kvm-1.5.0.pre2.tgz | openstack, kvm, micro |
1308
- # +--------------------------------------------------+-----------------------------+
1309
- #
1310
- # So to get the latest version for the filter tags,
1311
- # get the Name field, reverse sort, and return the first item
1312
- # Effectively:
1313
- # `#{bosh_stemcells_cmd} | grep micro | awk '{ print $2 }' | sort -r | head -n 1`.strip
1314
- stemcell_output = `#{bosh_stemcells_cmd}`
1315
- say stemcell_output
1316
- stemcell_output.scan(/[\w.-]+\.tgz/).last
1317
- end
1318
-
1319
- def provider_name
1320
- settings.bosh_provider
1321
- end
1322
-
1323
- # a helper object for the target BOSH provider
1324
- def provider
1325
- @provider ||= Bosh::Providers.for_bosh_provider_name(settings.bosh_provider, fog_compute)
1326
- end
1327
-
1328
- # The micro_bosh.yml that is uploaded to the Inception VM before deploying the
1329
- # MicroBOSH
1330
- def micro_bosh_yml
1331
- Bosh::Bootstrap::Stages::MicroBoshDeploy.new(settings).micro_bosh_manifest
1332
- end
1333
-
1334
- def cyan; "\033[36m" end
1335
- def clear; "\033[0m" end
1336
- def bold; "\033[1m" end
1337
- def red; "\033[31m" end
1338
- def green; "\033[32m" end
1339
- def yellow; "\033[33m" end
1340
-
1341
- # Helper to access HighLine for ask & menu prompts
1342
- def hl
1343
- @hl ||= HighLine.new
1344
- end
1345
- end
1346
- end
1347
- end