bosh-bootstrap 0.10.2 → 0.11.0

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.
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