vagrant-skytap 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/eng-10269.diff ADDED
@@ -0,0 +1,577 @@
1
+ # HG changeset patch
2
+ # Parent 586410d23ff4907e87ce5ee2c7eee574f0749ab0
3
+ # Parent 586410d23ff4907e87ce5ee2c7eee574f0749ab0
4
+ ENG-10269 add parallelization support for `vagrant up`.
5
+
6
+ diff -r 586410d23ff4 lib/vagrant-skytap/action.rb
7
+ --- a/lib/vagrant-skytap/action.rb Thu Nov 19 21:24:21 2015 -0800
8
+ +++ b/lib/vagrant-skytap/action.rb Thu Nov 19 21:50:44 2015 -0800
9
+ @@ -168,6 +168,11 @@
10
+ end
11
+ end
12
+
13
+ + # Some middlewares perform further actions after the succeeding
14
+ + # middleware returns. Provision and SyncedFolders, specifically,
15
+ + # both require the machine to be booted. This requirement can be
16
+ + # satisfied by putting the WaitForCommunicator middleware further
17
+ + # down in the sequence.
18
+ def self.action_prepare_boot
19
+ Vagrant::Action::Builder.new.tap do |b|
20
+ b.use PrepareNFSSettings
21
+ @@ -187,6 +192,14 @@
22
+ # This action is called to bring the box up from nothing.
23
+ def self.action_up
24
+ Vagrant::Action::Builder.new.tap do |b|
25
+ + b.use action_create
26
+ + b.use action_run_vm
27
+ + end
28
+ + end
29
+ +
30
+ + # This action is called by our modified "up" command.
31
+ + def self.action_create
32
+ + Vagrant::Action::Builder.new.tap do |b|
33
+ b.use HandleBox
34
+ b.use ConfigValidate
35
+ b.use InitializeAPIClient
36
+ @@ -204,23 +217,58 @@
37
+ b1.use StoreExtraData
38
+ b1.use SetUpVm
39
+ end
40
+ - b.use Call, IsRunning do |env, b1|
41
+ + b.use Call, IsStopped do |env, b1|
42
+ if env[:result]
43
+ + b1.use UpdateHardware
44
+ + b1.use SetHostname
45
+ + end
46
+ + end
47
+ + end
48
+ + end
49
+ +
50
+ +# # This action is called by our modified "up" command.
51
+ +# def self.action_update_properties
52
+ +# Vagrant::Action::Builder.new.tap do |b|
53
+ +# b.use InitializeAPIClient
54
+ +# b.use FetchEnvironment
55
+ +# b.use Call, IsStopped do |env, b1|
56
+ +# if env[:result]
57
+ +# b1.use UpdateHardware
58
+ +# b1.use SetHostname
59
+ +# end
60
+ +# end
61
+ +# end
62
+ +# end
63
+ +
64
+ + # This action is called by our modified "up" command after
65
+ + # all the VMs have been created. The action is called once
66
+ + # for each machine, but by default, the RunEnvironment
67
+ + # middleware will run all the machines in parallel; after
68
+ + # the first invocation, RunEnvironment is a no-op.
69
+ + def self.action_run_vm
70
+ + Vagrant::Action::Builder.new.tap do |b|
71
+ + b.use InitializeAPIClient
72
+ + b.use FetchEnvironment
73
+ + b.use Call, InitialState do |env, b1|
74
+ + case env[:result]
75
+ + when :running
76
+ b1.use MessageAlreadyRunning
77
+ next
78
+ + when :suspended
79
+ + b1.use Message, "The machine will be resumed"
80
+ + when :stopped
81
+ + b1.use action_prepare_boot
82
+ end
83
+
84
+ - b1.use Call, IsStopped do |env2, b2|
85
+ + b1.use Call, IsParallelized do |env2, b2|
86
+ if env2[:result]
87
+ - b2.use UpdateHardware
88
+ - b2.use SetHostname
89
+ - b2.use action_prepare_boot
90
+ + b2.use RunEnvironment
91
+ + else
92
+ + b2.use RunVm
93
+ end
94
+ -
95
+ - b2.use RunVm
96
+ - b2.use WaitForCommunicator
97
+ end
98
+ end
99
+ + b.use WaitForCommunicator
100
+ end
101
+ end
102
+
103
+ @@ -251,6 +299,8 @@
104
+ autoload :ExistenceCheck, action_root.join("existence_check")
105
+ autoload :FetchEnvironment, action_root.join("fetch_environment")
106
+ autoload :InitializeAPIClient, action_root.join("initialize_api_client")
107
+ + autoload :InitialState, action_root.join("initial_state")
108
+ + autoload :IsParallelized, action_root.join("is_parallelized")
109
+ autoload :IsRunning, action_root.join("is_running")
110
+ autoload :IsStopped, action_root.join("is_stopped")
111
+ autoload :IsSuspended, action_root.join("is_suspended")
112
+ @@ -263,6 +313,7 @@
113
+ autoload :PrepareNFSValidIds, action_root.join("prepare_nfs_valid_ids")
114
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
115
+ autoload :ReadState, action_root.join("read_state")
116
+ + autoload :RequiresBoot, action_root.join("requires_boot")
117
+ autoload :RunEnvironment, action_root.join("run_environment")
118
+ autoload :RunVm, action_root.join("run_vm")
119
+ autoload :SetHostname, action_root.join("set_hostname")
120
+ diff -r 586410d23ff4 lib/vagrant-skytap/action/initial_state.rb
121
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
122
+ +++ b/lib/vagrant-skytap/action/initial_state.rb Thu Nov 19 21:50:44 2015 -0800
123
+ @@ -0,0 +1,20 @@
124
+ +module VagrantPlugins
125
+ + module Skytap
126
+ + module Action
127
+ + # This is specifically for the "up" action. When we run in parallel, we have
128
+ + # to know which machines were initially powered off so we can set up operations
129
+ + # which will happen after the machine is ready
130
+ + class InitialState
131
+ + def initialize(app, env)
132
+ + @app = app
133
+ + @logger = Log4r::Logger.new("vagrant_skytap::action::initial_state")
134
+ + end
135
+ +
136
+ + def call(env)
137
+ + env[:result] = env[:initial_states][env[:machine].id]
138
+ + @app.call(env)
139
+ + end
140
+ + end
141
+ + end
142
+ + end
143
+ +end
144
+ diff -r 586410d23ff4 lib/vagrant-skytap/action/is_parallelized.rb
145
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
146
+ +++ b/lib/vagrant-skytap/action/is_parallelized.rb Thu Nov 19 21:50:44 2015 -0800
147
+ @@ -0,0 +1,21 @@
148
+ +module VagrantPlugins
149
+ + module Skytap
150
+ + module Action
151
+ + # This can be used with "Call" built-in to check if the action
152
+ + # is being performed as part of a parallel operation.
153
+ + class IsParallelized
154
+ + def initialize(app, env)
155
+ + @app = app
156
+ + @logger = Log4r::Logger.new("vagrant_skytap::action::is_parallelized")
157
+ + end
158
+ +
159
+ + def call(env)
160
+ + env[:result] = env[:parallel]
161
+ + @logger.info("Parallelization is #{env[:result] ? 'on' : 'off'}")
162
+ +
163
+ + @app.call(env)
164
+ + end
165
+ + end
166
+ + end
167
+ + end
168
+ +end
169
+ diff -r 586410d23ff4 lib/vagrant-skytap/action/requires_boot.rb
170
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
171
+ +++ b/lib/vagrant-skytap/action/requires_boot.rb Thu Nov 19 21:50:44 2015 -0800
172
+ @@ -0,0 +1,20 @@
173
+ +module VagrantPlugins
174
+ + module Skytap
175
+ + module Action
176
+ + # This can be used with "Call" built-in to check if the machine
177
+ + # was stopped at the beginning of the command and needs the prepare_boot
178
+ + # action. If this information is not captured,
179
+ + class RequiresBoot
180
+ + def initialize(app, env)
181
+ + @app = app
182
+ + @logger = Log4r::Logger.new("vagrant_skytap::action::requires_boot")
183
+ + end
184
+ +
185
+ + def call(env)
186
+ + env[:result] = env[:require_boot].collect(&:id).include?(env[:machine].id)
187
+ + @app.call(env)
188
+ + end
189
+ + end
190
+ + end
191
+ + end
192
+ +end
193
+ diff -r 586410d23ff4 lib/vagrant-skytap/action/run_environment.rb
194
+ --- a/lib/vagrant-skytap/action/run_environment.rb Thu Nov 19 21:24:21 2015 -0800
195
+ +++ b/lib/vagrant-skytap/action/run_environment.rb Thu Nov 19 21:50:44 2015 -0800
196
+ @@ -3,7 +3,8 @@
197
+ module VagrantPlugins
198
+ module Skytap
199
+ module Action
200
+ - # Runs the Skytap environment.
201
+ + # Runs multiple VMs in parallel. The :first_machine flag is used to prevent
202
+ + # redundant REST calls on subsequent invocations.
203
+ class RunEnvironment
204
+ include Vagrant::Util::Retryable
205
+
206
+ @@ -16,8 +17,14 @@
207
+ end
208
+
209
+ def call(env)
210
+ - env[:ui].info(I18n.t("vagrant_skytap.launching_instance"))
211
+ - environment.run!
212
+ + # Since the middleware sequence is called for each machine, use a
213
+ + # flag to ensure that we only make the request once.
214
+ + if env[:first_machine]
215
+ + env[:ui].info(I18n.t("vagrant_skytap.running_environment"))
216
+ + vm_ids = env[:machines].try(:collect, &:id)
217
+ + @logger.info("Running VMs: #{vm_ids}")
218
+ + env[:environment].run!(vm_ids)
219
+ + end
220
+
221
+ @app.call(env)
222
+ end
223
+ diff -r 586410d23ff4 lib/vagrant-skytap/api/environment.rb
224
+ --- a/lib/vagrant-skytap/api/environment.rb Thu Nov 19 21:24:21 2015 -0800
225
+ +++ b/lib/vagrant-skytap/api/environment.rb Thu Nov 19 21:50:44 2015 -0800
226
+ @@ -28,7 +28,9 @@
227
+ end
228
+
229
+ def properties(env)
230
+ - EnvironmentProperties.read(env[:machine].env.local_data_path)
231
+ + # This can be called outside the context of a particular machine
232
+ + path = env[:local_data_path] || env[:machine].env.local_data_path
233
+ + EnvironmentProperties.read(path)
234
+ end
235
+
236
+ def check_vm_before_adding(env, vm)
237
+ @@ -78,6 +80,10 @@
238
+ super
239
+ end
240
+
241
+ + def run!(vm_ids = nil)
242
+ + set_runstate :running, vm_ids: vm_ids
243
+ + end
244
+ +
245
+ def delete
246
+ retry_while_resource_busy do
247
+ api_client.delete(url)
248
+ diff -r 586410d23ff4 lib/vagrant-skytap/api/runstate_operations.rb
249
+ --- a/lib/vagrant-skytap/api/runstate_operations.rb Thu Nov 19 21:24:21 2015 -0800
250
+ +++ b/lib/vagrant-skytap/api/runstate_operations.rb Thu Nov 19 21:50:44 2015 -0800
251
+ @@ -20,12 +20,17 @@
252
+ end
253
+
254
+ def poweroff!
255
+ - set_runstate :halted, :stopped
256
+ + set_runstate :halted, completed_runstate: :stopped
257
+ end
258
+
259
+ - def set_runstate(new_runstate, completed_runstate = nil)
260
+ - completed_runstate ||= new_runstate
261
+ - update_with_retry(runstate: new_runstate)
262
+ + def set_runstate(new_runstate, opts = {})
263
+ + completed_runstate = opts.delete(:completed_runstate) || new_runstate
264
+ +
265
+ + params = {runstate: new_runstate}.tap do |ret|
266
+ + ret[:multiselect] = opts[:vm_ids] if opts[:vm_ids]
267
+ + end
268
+ + update_with_retry(params)
269
+ +
270
+ wait_for_runstate(completed_runstate) unless runstate == completed_runstate
271
+ end
272
+
273
+ diff -r 586410d23ff4 lib/vagrant-skytap/command/start_mixins.rb
274
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275
+ +++ b/lib/vagrant-skytap/command/start_mixins.rb Thu Nov 19 21:50:44 2015 -0800
276
+ @@ -0,0 +1,47 @@
277
+ +module VagrantPlugins
278
+ + module Skytap
279
+ + module Command
280
+ + module StartMixins
281
+ +
282
+ + # Would be nice to just extend this, then alias #build_start_options
283
+ + # and add default options flag.
284
+ + #include VagrantPlugins::CommandUp::StartMixins
285
+ +
286
+ + # This adds the standard `start` command line flags to the given
287
+ + # OptionParser, storing the result in the `options` dictionary.
288
+ + #
289
+ + # @param [OptionParser] parser
290
+ + # @param [Hash] options
291
+ + def build_start_options(parser, options)
292
+ + # Setup the defaults
293
+ + options[:provision_types] = nil
294
+ +
295
+ + # Add the options
296
+ + parser.on("--[no-]provision", "Enable or disable provisioning") do |p|
297
+ + options[:provision_enabled] = p
298
+ + options[:provision_ignore_sentinel] = true
299
+ + end
300
+ +
301
+ + parser.on("--provision-with x,y,z", Array,
302
+ + "Enable only certain provisioners, by type.") do |list|
303
+ + options[:provision_types] = list.map { |type| type.to_sym }
304
+ + options[:provision_enabled] = true
305
+ + options[:provision_ignore_sentinel] = true
306
+ + end
307
+ + end
308
+ +
309
+ + # This validates the provisioner flags and raises an exception
310
+ + # if there are invalid ones.
311
+ + def validate_provisioner_flags!(options)
312
+ + (options[:provision_types] || []).each do |type|
313
+ + klass = Vagrant.plugin("2").manager.provisioners[type]
314
+ + if !klass
315
+ + raise Vagrant::Errors::ProvisionerFlagInvalid,
316
+ + name: type.to_s
317
+ + end
318
+ + end
319
+ + end
320
+ + end
321
+ + end
322
+ + end
323
+ +end
324
+ diff -r 586410d23ff4 lib/vagrant-skytap/command/up.rb
325
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
326
+ +++ b/lib/vagrant-skytap/command/up.rb Thu Nov 19 21:50:44 2015 -0800
327
+ @@ -0,0 +1,138 @@
328
+ +require 'optparse'
329
+ +
330
+ +require "vagrant"
331
+ +require "byebug"
332
+ +
333
+ +require_relative 'start_mixins'
334
+ +
335
+ +# This is a modified copy of the built-in "up" command, which alters how
336
+ +# parallelization is implemented. Instead of making concurrent requests to run
337
+ +# individual VMs, we make a single REST call to update the runstates of
338
+ +# multiple VMs within the containing Skytap environment.
339
+ +
340
+ +module VagrantPlugins
341
+ + module Skytap
342
+ + module Command
343
+ + class Up < Vagrant.plugin("2", :command)
344
+ + include StartMixins
345
+ +
346
+ + def self.synopsis
347
+ + "starts and provisions the vagrant environment"
348
+ + end
349
+ +
350
+ + def execute
351
+ + options = {}
352
+ + options[:destroy_on_error] = true
353
+ + options[:parallel] = true
354
+ + options[:provision_ignore_sentinel] = false
355
+ +
356
+ + opts = OptionParser.new do |o|
357
+ + o.banner = "Usage: vagrant up [options] [name]"
358
+ + o.separator ""
359
+ + o.separator "Options:"
360
+ + o.separator ""
361
+ +
362
+ + build_start_options(o, options)
363
+ +
364
+ + o.on("--[no-]destroy-on-error",
365
+ + "Destroy machine if any fatal error happens (default to true)") do |destroy|
366
+ + options[:destroy_on_error] = destroy
367
+ + end
368
+ +
369
+ + o.on("--[no-]parallel",
370
+ + "Enable or disable parallelism if provider supports it") do |parallel|
371
+ + options[:parallel] = parallel
372
+ + end
373
+ +
374
+ + o.on("--provider PROVIDER", String,
375
+ + "Back the machine with a specific provider") do |provider|
376
+ + options[:provider] = provider
377
+ + end
378
+ + end
379
+ +
380
+ + # Parse the options
381
+ + argv = parse_options(opts)
382
+ + return if !argv
383
+ +
384
+ + # Validate the provisioners
385
+ + validate_provisioner_flags!(options)
386
+ +
387
+ + # Go over each VM and bring it up
388
+ + @logger.debug("'Up' each target VM...")
389
+ +
390
+ + # Create the VMs, then pass all the machines to the run action
391
+ + machines = []
392
+ + names = argv
393
+ + if names.empty?
394
+ + autostart = false
395
+ + @env.vagrantfile.machine_names_and_options.each do |n, o|
396
+ + autostart = true if o.key?(:autostart)
397
+ + o[:autostart] = true if !o.key?(:autostart)
398
+ + names << n.to_s if o[:autostart]
399
+ + end
400
+ +
401
+ + # If we have an autostart key but no names, it means that
402
+ + # all machines are autostart: false and we don't start anything.
403
+ + names = nil if autostart && names.empty?
404
+ + end
405
+ +
406
+ + if names
407
+ + with_target_vms(names, provider: options[:provider]) do |machine|
408
+ + @env.ui.info(I18n.t(
409
+ + "vagrant.commands.up.upping",
410
+ + name: machine.name,
411
+ + provider: machine.provider_name))
412
+ +
413
+ + machines << machine
414
+ + machine.action(:create, options)
415
+ + end
416
+ +
417
+ + # Capture states before the parallel runstate operation.
418
+ + # Checking state is relatively expensive. we should be smarter
419
+ + # about what information to capture. For example, we can
420
+ + # determine which machines were newly created, and put them in
421
+ + # the :stopped collection. Or call them :created? No, that
422
+ + # would likely be confusing
423
+ + #require_boot = machines.select{|m| m.state.id == :stopped}
424
+ + initial_states = machines.inject({}) do |acc, m|
425
+ + acc[m.id] = m.state.id
426
+ + acc
427
+ + end
428
+ +
429
+ + machines.each_with_index do |machine, i|
430
+ + machine.action(:run_vm, options.merge(
431
+ + first_machine: i == 0,
432
+ + machines: machines,
433
+ + #require_boot: require_boot,
434
+ + initial_states: initial_states
435
+ + ))
436
+ + end
437
+ + end
438
+ +
439
+ + if machines.empty?
440
+ + @env.ui.info(I18n.t("vagrant.up_no_machines"))
441
+ + return 0
442
+ + end
443
+ +
444
+ + # Output the post-up messages that we have, if any
445
+ + machines.each do |m|
446
+ + next if !m.config.vm.post_up_message
447
+ + next if m.config.vm.post_up_message == ""
448
+ +
449
+ + # Add a newline to separate things.
450
+ + @env.ui.info("", prefix: false)
451
+ +
452
+ + m.ui.success(I18n.t(
453
+ + "vagrant.post_up_message",
454
+ + name: m.name.to_s,
455
+ + message: m.config.vm.post_up_message))
456
+ + end
457
+ +
458
+ + # Success, exit status 0
459
+ + 0
460
+ + end
461
+ + end
462
+ + end
463
+ + end
464
+ +end
465
+ +
466
+ diff -r 586410d23ff4 lib/vagrant-skytap/plugin.rb
467
+ --- a/lib/vagrant-skytap/plugin.rb Thu Nov 19 21:24:21 2015 -0800
468
+ +++ b/lib/vagrant-skytap/plugin.rb Thu Nov 19 21:50:44 2015 -0800
469
+ @@ -24,7 +24,7 @@
470
+ Config
471
+ end
472
+
473
+ - provider(:skytap, parallel: false) do
474
+ + provider(:skytap, parallel: true) do
475
+ # Setup logging and i18n
476
+ setup_logging
477
+ setup_i18n
478
+ @@ -34,6 +34,11 @@
479
+ Provider
480
+ end
481
+
482
+ + command("up", primary: true) do
483
+ + require_relative "command/up"
484
+ + Command::Up
485
+ + end
486
+ +
487
+ # This initializes the internationalization strings.
488
+ def self.setup_i18n
489
+ I18n.load_path << File.expand_path("locales/en.yml", Skytap.source_root)
490
+ diff -r 586410d23ff4 locales/en.yml
491
+ --- a/locales/en.yml Thu Nov 19 21:24:21 2015 -0800
492
+ +++ b/locales/en.yml Thu Nov 19 21:50:44 2015 -0800
493
+ @@ -3,8 +3,8 @@
494
+ already_status: |-
495
+ The machine is already %{status}.
496
+
497
+ - launching_instance: |-
498
+ - Launching an instance with the following settings...
499
+ + running_environment: |-
500
+ + Starting VMs ...
501
+ launching_vm: |-
502
+ Launching a VM with the following settings...
503
+ not_created: |-
504
+ @@ -53,6 +53,11 @@
505
+ vm_url_required:
506
+ The URL of a Skytap VM must be specified via "vm_url"
507
+
508
+ + commands:
509
+ + up:
510
+ + creating: |-
511
+ + Creating machine '%{name}' with '%{provider}' provider...
512
+ +
513
+ errors:
514
+ instance_ready_timeout: |-
515
+ The instance never became "ready" in Skytap. The timeout currently
516
+ diff -r 586410d23ff4 spec/acceptance/provider/up_spec.rb
517
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
518
+ +++ b/spec/acceptance/provider/up_spec.rb Thu Nov 19 21:50:44 2015 -0800
519
+ @@ -0,0 +1,33 @@
520
+ +# This tests that an instance can be halted correctly
521
+ +shared_examples 'provider/up' do |provider, options|
522
+ + if !options[:box]
523
+ + raise ArgumentError,
524
+ + "box option must be specified for provider: #{provider}"
525
+ + end
526
+ +
527
+ + include_context 'acceptance'
528
+ +
529
+ + before do
530
+ + environment.skeleton('generic')
531
+ + #assert_execute('vagrant', 'box', 'add', 'basic', options[:box])
532
+ + end
533
+ +
534
+ + after do
535
+ + assert_execute('vagrant', 'destroy', '--force')
536
+ + end
537
+ +
538
+ + it 'should bring up the machine and halt it' do
539
+ + status("Test: machine can be brought up")
540
+ + up_result = execute("vagrant", "up")
541
+ + expect(up_result).to exit_with(0)
542
+ +
543
+ + status("Test: machine is running after up")
544
+ + echo_result = execute("vagrant", "ssh", "-c", "echo foo")
545
+ + expect(echo_result).to exit_with(0)
546
+ + expect(echo_result.stdout).to match(/foo\n$/)
547
+ +
548
+ + status("Test: machine can be halted")
549
+ + halt_result = execute("vagrant", "halt")
550
+ + expect(halt_result).to exit_with(0)
551
+ + end
552
+ +end
553
+ diff -r 586410d23ff4 spec/acceptance/skeletons/generic/Vagrantfile
554
+ --- a/spec/acceptance/skeletons/generic/Vagrantfile Thu Nov 19 21:24:21 2015 -0800
555
+ +++ b/spec/acceptance/skeletons/generic/Vagrantfile Thu Nov 19 21:50:44 2015 -0800
556
+ @@ -1,15 +1,14 @@
557
+ Vagrant.configure("2") do |config|
558
+ - config.vm.box = "skytap-dummy"
559
+ + config.vm.box = "skytap/empty"
560
+
561
+ config.vm.provider :skytap do |skytap, override|
562
+ - skytap.username = "user"
563
+ - skytap.api_token = "9999999999999999999999"
564
+ - skytap.base_url = "https://example.com/"
565
+ + skytap.vm_url = "/vms/7285844"
566
+ + skytap.vpn_url = "/vpns/vpn-711360"
567
+ +# skytap.vpn_url = "/vpns/vpn-3195669"
568
+ end
569
+
570
+ config.vm.define "vm1" do |ubuntu|
571
+ - ubuntu.vm.provider :skytap do |box|
572
+ - box.vm_url = "https://example.com/vms/1"
573
+ - end
574
+ + ubuntu.ssh.username = "skytap"
575
+ + ubuntu.ssh.password = "ChangeMe!"
576
+ end
577
+ end