vagrant-cloudstack 1.3.0 → 1.4.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -19
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +19 -19
  5. data/CHANGELOG.md +179 -171
  6. data/Docker/.dockerignore +2 -0
  7. data/Docker/Dockerfile +51 -0
  8. data/Docker/Dockerfile.chefdk_0_17 +49 -0
  9. data/Docker/Dockerfile.latest_dependencies +49 -0
  10. data/Docker/README.md +67 -0
  11. data/Docker/vac.ps1 +29 -0
  12. data/Docker/vac.sh +30 -0
  13. data/Gemfile +20 -20
  14. data/LICENSE +8 -8
  15. data/README.md +416 -416
  16. data/Rakefile +106 -99
  17. data/bootstrap.key +27 -0
  18. data/build_rpm.sh +7 -7
  19. data/functional-tests/basic/Vagrantfile.basic_networking +45 -45
  20. data/functional-tests/basic/basic_spec.rb +21 -21
  21. data/functional-tests/networking/Vagrantfile.advanced_networking +119 -102
  22. data/functional-tests/networking/networking_spec.rb +14 -0
  23. data/functional-tests/rsync/Vagrantfile.advanced_networking +39 -56
  24. data/functional-tests/rsync/rsync_spec.rb +9 -9
  25. data/functional-tests/vmlifecycle/Vagrantfile.advanced_networking +66 -82
  26. data/functional-tests/vmlifecycle/vmlifecycle_spec.rb +13 -13
  27. data/lib/vagrant-cloudstack/action/connect_cloudstack.rb +47 -47
  28. data/lib/vagrant-cloudstack/action/is_created.rb +18 -18
  29. data/lib/vagrant-cloudstack/action/is_stopped.rb +18 -18
  30. data/lib/vagrant-cloudstack/action/message_already_created.rb +16 -16
  31. data/lib/vagrant-cloudstack/action/message_not_created.rb +16 -16
  32. data/lib/vagrant-cloudstack/action/message_will_not_destroy.rb +16 -16
  33. data/lib/vagrant-cloudstack/action/read_rdp_info.rb +76 -76
  34. data/lib/vagrant-cloudstack/action/read_ssh_info.rb +104 -87
  35. data/lib/vagrant-cloudstack/action/read_state.rb +38 -38
  36. data/lib/vagrant-cloudstack/action/read_winrm_info.rb +103 -103
  37. data/lib/vagrant-cloudstack/action/run_instance.rb +798 -703
  38. data/lib/vagrant-cloudstack/action/start_instance.rb +81 -81
  39. data/lib/vagrant-cloudstack/action/stop_instance.rb +28 -28
  40. data/lib/vagrant-cloudstack/action/terminate_instance.rb +269 -224
  41. data/lib/vagrant-cloudstack/action/timed_provision.rb +21 -21
  42. data/lib/vagrant-cloudstack/action/wait_for_state.rb +41 -41
  43. data/lib/vagrant-cloudstack/action/warn_networks.rb +19 -19
  44. data/lib/vagrant-cloudstack/action.rb +210 -210
  45. data/lib/vagrant-cloudstack/capabilities/rdp.rb +12 -12
  46. data/lib/vagrant-cloudstack/capabilities/winrm.rb +12 -12
  47. data/lib/vagrant-cloudstack/config.rb +566 -548
  48. data/lib/vagrant-cloudstack/errors.rb +27 -27
  49. data/lib/vagrant-cloudstack/exceptions/exceptions.rb +10 -10
  50. data/lib/vagrant-cloudstack/model/cloudstack_resource.rb +51 -33
  51. data/lib/vagrant-cloudstack/plugin.rb +82 -82
  52. data/lib/vagrant-cloudstack/provider.rb +58 -58
  53. data/lib/vagrant-cloudstack/service/cloudstack_resource_service.rb +64 -58
  54. data/lib/vagrant-cloudstack/util/timer.rb +17 -17
  55. data/lib/vagrant-cloudstack/version.rb +5 -5
  56. data/lib/vagrant-cloudstack.rb +17 -17
  57. data/locales/en.yml +131 -123
  58. data/spec/spec_helper.rb +8 -6
  59. data/spec/vagrant-cloudstack/action/read_ssh_info_spec.rb +80 -0
  60. data/spec/vagrant-cloudstack/config_spec.rb +355 -355
  61. data/spec/vagrant-cloudstack/model/cloudstack_resource_spec.rb +95 -73
  62. data/spec/vagrant-cloudstack/service/cloudstack_resource_service_spec.rb +43 -43
  63. data/spec/vagrant-cloudstack/support/be_a_resource.rb +6 -0
  64. data/vagrant-cloudstack.gemspec +59 -59
  65. data/vagrant-cloudstack.spec +42 -42
  66. metadata +14 -7
  67. data/dummy.box +0 -0
  68. data/example_box/README.md +0 -13
  69. data/example_box/metadata.json +0 -3
  70. data/functional-tests/networking/rsync_spec.rb +0 -12
@@ -1,12 +1,12 @@
1
- module VagrantPlugins
2
- module Cloudstack
3
- module Cap
4
- class Rdp
5
- def self.rdp_info(machine)
6
- env = machine.action('read_rdp_info')
7
- env[:machine_rdp_info]
8
- end
9
- end
10
- end
11
- end
12
- end
1
+ module VagrantPlugins
2
+ module Cloudstack
3
+ module Cap
4
+ class Rdp
5
+ def self.rdp_info(machine)
6
+ env = machine.action('read_rdp_info')
7
+ env[:machine_rdp_info]
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,12 +1,12 @@
1
- module VagrantPlugins
2
- module Cloudstack
3
- module Cap
4
- class WinRM
5
- def self.winrm_info(machine)
6
- env = machine.action('read_winrm_info')
7
- env[:machine_winrm_info]
8
- end
9
- end
10
- end
11
- end
12
- end
1
+ module VagrantPlugins
2
+ module Cloudstack
3
+ module Cap
4
+ class WinRM
5
+ def self.winrm_info(machine)
6
+ env = machine.action('read_winrm_info')
7
+ env[:machine_winrm_info]
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,548 +1,566 @@
1
- require "vagrant"
2
-
3
- module VagrantPlugins
4
- module Cloudstack
5
- class Config < Vagrant.plugin("2", :config)
6
- # Cloudstack api host.
7
- #
8
- # @return [String]
9
- attr_accessor :host
10
-
11
- # Hostname for the machine instance
12
- # This will be passed through to the api.
13
- #
14
- # @return [String]
15
- attr_accessor :name
16
-
17
- # Cloudstack api path.
18
- #
19
- # @return [String]
20
- attr_accessor :path
21
-
22
- # Cloudstack api port.
23
- #
24
- # @return [String]
25
- attr_accessor :port
26
-
27
- # Cloudstack api scheme
28
- #
29
- # @return [String]
30
- attr_accessor :scheme
31
-
32
- # The API key for accessing Cloudstack.
33
- #
34
- # @return [String]
35
- attr_accessor :api_key
36
-
37
- # The secret key for accessing Cloudstack.
38
- #
39
- # @return [String]
40
- attr_accessor :secret_key
41
-
42
- # The timeout to wait for an instance to become ready.
43
- #
44
- # @return [Fixnum]
45
- attr_accessor :instance_ready_timeout
46
-
47
- # Domain id to launch the instance into.
48
- #
49
- # @return [String]
50
- attr_accessor :domain_id
51
-
52
- # Network uuid that the instance should use
53
- #
54
- # @return [String]
55
- attr_accessor :network_id
56
-
57
- # Network name that the instance should use
58
- #
59
- # @return [String]
60
- attr_accessor :network_name
61
-
62
- # Network Type
63
- #
64
- # @return [String]
65
- attr_accessor :network_type
66
-
67
- # Project uuid that the instance should belong to
68
- #
69
- # @return [String]
70
- attr_accessor :project_id
71
-
72
- # Service offering uuid to use for the instance
73
- #
74
- # @return [String]
75
- attr_accessor :service_offering_id
76
-
77
- # Service offering name to use for the instance
78
- #
79
- # @return [String]
80
- attr_accessor :service_offering_name
81
-
82
- # Disk offering uuid to use for the instance
83
- #
84
- # @return [String]
85
- attr_accessor :disk_offering_id
86
-
87
- # Disk offering name to use for the instance
88
- #
89
- # @return [String]
90
- attr_accessor :disk_offering_name
91
-
92
- # Template uuid to use for the instance
93
- #
94
- # @return [String]
95
- attr_accessor :template_id
96
-
97
- # Template name to use for the instance
98
- #
99
- # @return [String]
100
- attr_accessor :template_name
101
-
102
- # Zone uuid to launch the instance into. If nil, it will
103
- # launch in default project.
104
- #
105
- # @return [String]
106
- attr_accessor :zone_id
107
-
108
- # Zone name to launch the instance into. If nil, it will
109
- # launch in default project.
110
- #
111
- # @return [String]
112
- attr_accessor :zone_name
113
-
114
- # The name of the keypair to use.
115
- #
116
- # @return [String]
117
- attr_accessor :keypair
118
-
119
- # Paramters for Static NAT
120
- #
121
- # @return [String]
122
- attr_accessor :static_nat
123
-
124
- # IP address id to use for port forwarding rule
125
- #
126
- # @return [String]
127
- attr_accessor :pf_ip_address_id
128
-
129
- # IP address to use for port forwarding rule
130
- #
131
- # @return [String]
132
- attr_accessor :pf_ip_address
133
-
134
- # public port to use for port forwarding rule
135
- #
136
- # @return [String]
137
- attr_accessor :pf_public_port
138
-
139
- # public port to use for port forwarding rule
140
- #
141
- # @return [String]
142
- attr_accessor :pf_public_rdp_port
143
-
144
- # private port to use for port forwarding rule
145
- #
146
- # @return [String]
147
- attr_accessor :pf_private_rdp_port
148
-
149
- # public port to use for port forwarding rule
150
- #
151
- # @return [Range]
152
- attr_accessor :pf_public_port_randomrange
153
-
154
- # private port to use for port forwarding rule
155
- #
156
- # @return [String]
157
- attr_accessor :pf_private_port
158
-
159
- # flag to enable/disable automatic open firewall rule
160
- #
161
- # @return [Boolean]
162
- attr_accessor :pf_open_firewall
163
-
164
- # CIDR List string of trusted networks
165
- #
166
- # @return [String]
167
- attr_accessor :pf_trusted_networks
168
-
169
- # comma separated list of port forwarding rules
170
- # (hash with rule parameters)
171
- #
172
- # @return [Array]
173
- attr_accessor :port_forwarding_rules
174
-
175
- # comma separated list of firewall rules
176
- # (hash with rule parameters)
177
- #
178
- # @return [Array]
179
- attr_accessor :firewall_rules
180
-
181
- # comma separated list of security groups id that going
182
- # to be applied to the virtual machine.
183
- #
184
- # @return [Array]
185
- attr_accessor :security_group_ids
186
-
187
- # comma separated list of security groups name that going
188
- # to be applied to the virtual machine.
189
- #
190
- # @return [Array]
191
- attr_accessor :security_group_names
192
-
193
- # comma separated list of security groups
194
- # (hash with ingress/egress rules)
195
- # to be applied to the virtual machine.
196
- #
197
- # @return [Array]
198
- attr_accessor :security_groups
199
-
200
- # display name for the instance
201
- #
202
- # @return [String]
203
- attr_accessor :display_name
204
-
205
- # group for the instance
206
- #
207
- # @return [String]
208
- attr_accessor :group
209
-
210
- # The user data string
211
- #
212
- # @return [String]
213
- attr_accessor :user_data
214
-
215
- # The key to be used when loging in to the vm via ssh
216
- #
217
- # @return [String]
218
- attr_accessor :ssh_key
219
-
220
- # The username to be used when loging in to the vm via ssh
221
- #
222
- # @return [String]
223
- attr_accessor :ssh_user
224
-
225
- # The username to be used when loging in to the vm
226
- #
227
- # @return [String]
228
- attr_accessor :vm_user
229
-
230
- # The username to be used when loging in to the vm
231
- #
232
- # @return [String]
233
- attr_accessor :vm_password
234
-
235
- # Private ip for the instance
236
- #
237
- # @return [String]
238
- attr_accessor :private_ip_address
239
-
240
- # flag to enable/disable expunge vm on destroy
241
- #
242
- # @return [Boolean]
243
- attr_accessor :expunge_on_destroy
244
-
245
- def initialize(domain_specific=false)
246
- @host = UNSET_VALUE
247
- @name = UNSET_VALUE
248
- @path = UNSET_VALUE
249
- @port = UNSET_VALUE
250
- @scheme = UNSET_VALUE
251
- @api_key = UNSET_VALUE
252
- @secret_key = UNSET_VALUE
253
- @instance_ready_timeout = UNSET_VALUE
254
- @domain_id = UNSET_VALUE
255
- @network_id = UNSET_VALUE
256
- @network_name = UNSET_VALUE
257
- @network_type = UNSET_VALUE
258
- @project_id = UNSET_VALUE
259
- @service_offering_id = UNSET_VALUE
260
- @service_offering_name = UNSET_VALUE
261
- @template_id = UNSET_VALUE
262
- @template_name = UNSET_VALUE
263
- @zone_id = UNSET_VALUE
264
- @zone_name = UNSET_VALUE
265
- @keypair = UNSET_VALUE
266
- @static_nat = UNSET_VALUE
267
- @pf_ip_address_id = UNSET_VALUE
268
- @pf_ip_address = UNSET_VALUE
269
- @pf_public_port = UNSET_VALUE
270
- @pf_public_rdp_port = UNSET_VALUE
271
- @pf_private_rdp_port = UNSET_VALUE
272
- @pf_public_port_randomrange= UNSET_VALUE
273
- @pf_private_port = UNSET_VALUE
274
- @pf_open_firewall = UNSET_VALUE
275
- @pf_trusted_networks = UNSET_VALUE
276
- @port_forwarding_rules = UNSET_VALUE
277
- @firewall_rules = UNSET_VALUE
278
- @security_group_ids = UNSET_VALUE
279
- @display_name = UNSET_VALUE
280
- @group = UNSET_VALUE
281
- @security_group_names = UNSET_VALUE
282
- @security_groups = UNSET_VALUE
283
- @user_data = UNSET_VALUE
284
- @ssh_key = UNSET_VALUE
285
- @ssh_user = UNSET_VALUE
286
- @vm_user = UNSET_VALUE
287
- @vm_password = UNSET_VALUE
288
- @private_ip_address = UNSET_VALUE
289
- @expunge_on_destroy = UNSET_VALUE
290
-
291
- # Internal state (prefix with __ so they aren't automatically
292
- # merged)
293
- @__compiled_domain_configs = {}
294
- @__finalized = false
295
- @__domain_config = {}
296
- @__domain_specific = domain_specific
297
- end
298
-
299
- # Allows domain-specific overrides of any of the settings on this
300
- # configuration object. This allows the user to override things like
301
- # template and keypair name for domains. Example:
302
- #
303
- # cloudstack.domain_config "abcd-ef01-2345-6789" do |domain|
304
- # domain.template_id = "1234-5678-90ab-cdef"
305
- # domain.keypair_name = "company-east"
306
- # end
307
- #
308
- # @param [String] domain The Domain name to configure.
309
- # @param [Hash] attributes Direct attributes to set on the configuration
310
- # as a shortcut instead of specifying a full block.
311
- # @yield [config] Yields a new domain configuration.
312
- def domain_config(domain, attributes=nil, &block)
313
- # Append the block to the list of domain configs for that domain.
314
- # We'll evaluate these upon finalization.
315
- @__domain_config[domain] ||= []
316
-
317
- # Append a block that sets attributes if we got one
318
- if attributes
319
- attr_block = lambda do |config|
320
- config.set_options(attributes)
321
- end
322
-
323
- @__domain_config[domain] << attr_block
324
- end
325
-
326
- # Append a block if we got one
327
- @__domain_config[domain] << block if block_given?
328
- end
329
-
330
- #-------------------------------------------------------------------
331
- # Internal methods.
332
- #-------------------------------------------------------------------
333
-
334
- def merge(other)
335
- super.tap do |result|
336
- # Copy over the domain specific flag. "True" is retained if either
337
- # has it.
338
- new_domain_specific = other.instance_variable_get(:@__domain_specific)
339
- result.instance_variable_set(
340
- :@__domain_specific, new_domain_specific || @__domain_specific)
341
-
342
- # Go through all the domain configs and prepend ours onto
343
- # theirs.
344
- new_domain_config = other.instance_variable_get(:@__domain_config)
345
- @__domain_config.each do |key, value|
346
- new_domain_config[key] ||= []
347
- new_domain_config[key] = value + new_domain_config[key]
348
- end
349
-
350
- # Set it
351
- result.instance_variable_set(:@__domain_config, new_domain_config)
352
-
353
- # Merge in the tags
354
- result.tags.merge!(self.tags)
355
- result.tags.merge!(other.tags)
356
- end
357
- end
358
-
359
- def finalize!
360
- # Host must be nil, since we can't default that
361
- @host = nil if @host == UNSET_VALUE
362
-
363
- # Name must be nil, since we can't default that
364
- @name = nil if @name == UNSET_VALUE
365
-
366
- # Path must be nil, since we can't default that
367
- @path = nil if @path == UNSET_VALUE
368
-
369
- # Port must be nil, since we can't default that
370
- @port = nil if @port == UNSET_VALUE
371
-
372
- # We default the scheme to whatever the user has specifid in the .fog file
373
- # *OR* whatever is default for the provider in the fog library
374
- @scheme = nil if @scheme == UNSET_VALUE
375
-
376
- # Try to get access keys from environment variables, they will
377
- # default to nil if the environment variables are not present
378
- @api_key = ENV['CLOUDSTACK_API_KEY'] if @api_key == UNSET_VALUE
379
- @secret_key = ENV['CLOUDSTACK_SECRET_KEY'] if @secret_key == UNSET_VALUE
380
-
381
- # Set the default timeout for waiting for an instance to be ready
382
- @instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
383
-
384
- # Domain id must be nil, since we can't default that
385
- @domain_id = nil if @domain_id == UNSET_VALUE
386
-
387
- # Network uuid must be nil, since we can't default that
388
- @network_id = nil if @network_id == UNSET_VALUE
389
-
390
- # Network uuid must be nil, since we can't default that
391
- @network_name = nil if @network_name == UNSET_VALUE
392
-
393
- # NetworkType is 'Advanced' by default
394
- @network_type = "Advanced" if @network_type == UNSET_VALUE
395
-
396
- # Project uuid must be nil, since we can't default that
397
- @project_id = nil if @project_id == UNSET_VALUE
398
-
399
- # Service offering uuid must be nil, since we can't default that
400
- @service_offering_id = nil if @service_offering_id == UNSET_VALUE
401
-
402
- # Service offering name must be nil, since we can't default that
403
- @service_offering_name = nil if @service_offering_name == UNSET_VALUE
404
-
405
- # Template uuid must be nil, since we can't default that
406
- @template_id = nil if @template_id == UNSET_VALUE
407
-
408
- # Template name must be nil, since we can't default that
409
- @template_name = nil if @template_name == UNSET_VALUE
410
-
411
- # Zone uuid must be nil, since we can't default that
412
- @zone_id = nil if @zone_id == UNSET_VALUE
413
-
414
- # Zone uuid must be nil, since we can't default that
415
- @zone_name = nil if @zone_name == UNSET_VALUE
416
-
417
- # Keypair defaults to nil
418
- @keypair = nil if @keypair == UNSET_VALUE
419
-
420
- # Static NAT must be empty array
421
- @static_nat = [] if @static_nat == UNSET_VALUE
422
-
423
- # IP address id must be nil, since we can't default that
424
- @pf_ip_address_id = nil if @pf_ip_address_id == UNSET_VALUE
425
-
426
- # IP address must be nil, since we can't default that
427
- @pf_ip_address = nil if @pf_ip_address == UNSET_VALUE
428
-
429
- # Public port must be nil, since we can't default that
430
- @pf_public_port = nil if @pf_public_port == UNSET_VALUE
431
-
432
- # Public port must be nil, since we can't default that
433
- @pf_public_rdp_port = nil if @pf_public_rdp_port == UNSET_VALUE
434
-
435
- # Private rdp port defaults to 3389
436
- @pf_private_rdp_port = 3389 if @pf_private_rdp_port == UNSET_VALUE
437
-
438
- # Public port random-range, default to rfc6335 'Dynamic Ports'; "(never assigned)"
439
- @pf_public_port_randomrange = {:start=>49160, :end=>49200} if @pf_public_port_randomrange == UNSET_VALUE
440
-
441
- # Private port must be nil, since we can't default that
442
- @pf_private_port = nil if @pf_private_port == UNSET_VALUE
443
-
444
- # Open firewall is true by default (for backwards compatibility)
445
- @pf_open_firewall = true if @pf_open_firewall == UNSET_VALUE
446
-
447
- # Trusted networks must be nil, since we can't default that
448
- @pf_trusted_networks = nil if @pf_trusted_networks == UNSET_VALUE
449
-
450
- # Port forwarding rules must be empty array
451
- @port_forwarding_rules = [] if @port_forwarding_rules == UNSET_VALUE
452
-
453
- # Firewall rules must be empty array
454
- @firewall_rules = [] if @firewall_rules == UNSET_VALUE
455
-
456
- # Security Group IDs must be nil, since we can't default that
457
- @security_group_ids = [] if @security_group_ids == UNSET_VALUE
458
-
459
- # Security Group Names must be nil, since we can't default that
460
- @security_group_names = [] if @security_group_names == UNSET_VALUE
461
-
462
- # Security Groups must be nil, since we can't default that
463
- @security_groups = [] if @security_groups == UNSET_VALUE
464
-
465
- # Display name must be nil, since we can't default that
466
- @display_name = nil if @display_name == UNSET_VALUE
467
-
468
- # Group must be nil, since we can't default that
469
- @group = nil if @group == UNSET_VALUE
470
-
471
- # User Data is nil by default
472
- @user_data = nil if @user_data == UNSET_VALUE
473
-
474
- # ssh key is nil by default
475
- @ssh_key = nil if @ssh_key == UNSET_VALUE
476
-
477
- # ssh user is nil by default
478
- @ssh_user = nil if @ssh_user == UNSET_VALUE
479
-
480
- # vm user is nil by default
481
- @vm_user = nil if @vm_user == UNSET_VALUE
482
-
483
- # vm password is nil by default
484
- @vm_password = nil if @vm_password == UNSET_VALUE
485
-
486
- # private ip is nil by default
487
- @private_ip_address = nil if @private_ip_address == UNSET_VALUE
488
-
489
- # expunge on destroy is nil by default
490
- @expunge_on_destroy = false if @expunge_on_destroy == UNSET_VALUE
491
-
492
- # Compile our domain specific configurations only within
493
- # NON-DOMAIN-SPECIFIC configurations.
494
- if !@__domain_specific
495
- @__domain_config.each do |domain, blocks|
496
- config = self.class.new(true).merge(self)
497
-
498
- # Execute the configuration for each block
499
- blocks.each { |b| b.call(config) }
500
-
501
- # The domain name of the configuration always equals the
502
- # domain config name:
503
- config.domain = domain
504
-
505
- # Finalize the configuration
506
- config.finalize!
507
-
508
- # Store it for retrieval
509
- @__compiled_domain_configs[domain] = config
510
- end
511
- end
512
-
513
- # Mark that we finalized
514
- @__finalized = true
515
- end
516
-
517
- def validate(machine)
518
- errors = []
519
-
520
- if @domain
521
- # Get the configuration for the domain we're using and validate only
522
- # that domain.
523
- config = get_domain_config(@domain)
524
-
525
- if !config.use_fog_profile
526
- errors << I18n.t("vagrant_cloudstack.config.api_key_required") if \
527
- config.access_key_id.nil?
528
- errors << I18n.t("vagrant_cloudstack.config.secret_key_required") if \
529
- config.secret_access_key.nil?
530
- end
531
- end
532
-
533
- {"Cloudstack Provider" => errors}
534
- end
535
-
536
- # This gets the configuration for a specific domain. It shouldn't
537
- # be called by the general public and is only used internally.
538
- def get_domain_config(name)
539
- if !@__finalized
540
- raise "Configuration must be finalized before calling this method."
541
- end
542
-
543
- # Return the compiled domain config
544
- @__compiled_domain_configs[name] || self
545
- end
546
- end
547
- end
548
- end
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module Cloudstack
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # Cloudstack api host.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :host
10
+
11
+ # Hostname for the machine instance
12
+ # This will be passed through to the api.
13
+ #
14
+ # @return [String]
15
+ attr_accessor :name
16
+
17
+ # Cloudstack api path.
18
+ #
19
+ # @return [String]
20
+ attr_accessor :path
21
+
22
+ # Cloudstack api port.
23
+ #
24
+ # @return [String]
25
+ attr_accessor :port
26
+
27
+ # Cloudstack api scheme
28
+ #
29
+ # @return [String]
30
+ attr_accessor :scheme
31
+
32
+ # The API key for accessing Cloudstack.
33
+ #
34
+ # @return [String]
35
+ attr_accessor :api_key
36
+
37
+ # The secret key for accessing Cloudstack.
38
+ #
39
+ # @return [String]
40
+ attr_accessor :secret_key
41
+
42
+ # The timeout to wait for an instance to become ready.
43
+ #
44
+ # @return [Fixnum]
45
+ attr_accessor :instance_ready_timeout
46
+
47
+ # Domain id to launch the instance into.
48
+ #
49
+ # @return [String]
50
+ attr_accessor :domain_id
51
+
52
+ # Network uuid(s) that the instance should use
53
+ #
54
+ # @return [String,Array]
55
+ attr_accessor :network_id
56
+
57
+ # Network name(s) that the instance should use
58
+ #
59
+ # @return [String,Array]
60
+ attr_accessor :network_name
61
+
62
+ # Network Type
63
+ #
64
+ # @return [String]
65
+ attr_accessor :network_type
66
+
67
+ # Project uuid that the instance should belong to
68
+ #
69
+ # @return [String]
70
+ attr_accessor :project_id
71
+
72
+ # Service offering uuid to use for the instance
73
+ #
74
+ # @return [String]
75
+ attr_accessor :service_offering_id
76
+
77
+ # Service offering name to use for the instance
78
+ #
79
+ # @return [String]
80
+ attr_accessor :service_offering_name
81
+
82
+ # Disk offering uuid to use for the instance
83
+ #
84
+ # @return [String]
85
+ attr_accessor :disk_offering_id
86
+
87
+ # Disk offering name to use for the instance
88
+ #
89
+ # @return [String]
90
+ attr_accessor :disk_offering_name
91
+
92
+ # Template uuid to use for the instance
93
+ #
94
+ # @return [String]
95
+ attr_accessor :template_id
96
+
97
+ # Template name to use for the instance
98
+ #
99
+ # @return [String]
100
+ attr_accessor :template_name
101
+
102
+ # Zone uuid to launch the instance into. If nil, it will
103
+ # launch in default project.
104
+ #
105
+ # @return [String]
106
+ attr_accessor :zone_id
107
+
108
+ # Zone name to launch the instance into. If nil, it will
109
+ # launch in default project.
110
+ #
111
+ # @return [String]
112
+ attr_accessor :zone_name
113
+
114
+ # The name of the keypair to use.
115
+ #
116
+ # @return [String]
117
+ attr_accessor :keypair
118
+
119
+ # Paramters for Static NAT
120
+ #
121
+ # @return [String]
122
+ attr_accessor :static_nat
123
+
124
+ # IP address id to use for port forwarding rule
125
+ #
126
+ # @return [String]
127
+ attr_accessor :pf_ip_address_id
128
+
129
+ # IP address to use for port forwarding rule
130
+ #
131
+ # @return [String]
132
+ attr_accessor :pf_ip_address
133
+
134
+ # public port to use for port forwarding rule
135
+ #
136
+ # @return [String]
137
+ attr_accessor :pf_public_port
138
+
139
+ # public port to use for port forwarding rule
140
+ #
141
+ # @return [String]
142
+ attr_accessor :pf_public_rdp_port
143
+
144
+ # private port to use for port forwarding rule
145
+ #
146
+ # @return [String]
147
+ attr_accessor :pf_private_rdp_port
148
+
149
+ # public port to use for port forwarding rule
150
+ #
151
+ # @return [Range]
152
+ attr_accessor :pf_public_port_randomrange
153
+
154
+ # private port to use for port forwarding rule
155
+ #
156
+ # @return [String]
157
+ attr_accessor :pf_private_port
158
+
159
+ # flag to enable/disable automatic open firewall rule
160
+ #
161
+ # @return [Boolean]
162
+ attr_accessor :pf_open_firewall
163
+
164
+ # CIDR List string of trusted networks
165
+ #
166
+ # @return [String]
167
+ attr_accessor :pf_trusted_networks
168
+
169
+ # comma separated list of port forwarding rules
170
+ # (hash with rule parameters)
171
+ #
172
+ # @return [Array]
173
+ attr_accessor :port_forwarding_rules
174
+
175
+ # comma separated list of firewall rules
176
+ # (hash with rule parameters)
177
+ #
178
+ # @return [Array]
179
+ attr_accessor :firewall_rules
180
+
181
+ # comma separated list of security groups id that going
182
+ # to be applied to the virtual machine.
183
+ #
184
+ # @return [Array]
185
+ attr_accessor :security_group_ids
186
+
187
+ # comma separated list of security groups name that going
188
+ # to be applied to the virtual machine.
189
+ #
190
+ # @return [Array]
191
+ attr_accessor :security_group_names
192
+
193
+ # comma separated list of security groups
194
+ # (hash with ingress/egress rules)
195
+ # to be applied to the virtual machine.
196
+ #
197
+ # @return [Array]
198
+ attr_accessor :security_groups
199
+
200
+ # display name for the instance
201
+ #
202
+ # @return [String]
203
+ attr_accessor :display_name
204
+
205
+ # group for the instance
206
+ #
207
+ # @return [String]
208
+ attr_accessor :group
209
+
210
+ # The user data string
211
+ #
212
+ # @return [String]
213
+ attr_accessor :user_data
214
+
215
+ # The key to be used when loging in to the vm via ssh
216
+ #
217
+ # @return [String]
218
+ attr_accessor :ssh_key
219
+
220
+ # The username to be used when loging in to the vm via ssh
221
+ #
222
+ # @return [String]
223
+ attr_accessor :ssh_user
224
+
225
+ # The network_id to be used when loging in to the vm via ssh
226
+ #
227
+ # @return [String]
228
+ attr_accessor :ssh_network_id
229
+
230
+ # The network_name to be used when loging in to the vm via ssh
231
+ #
232
+ # @return [String]
233
+ attr_accessor :ssh_network_name
234
+
235
+ # The username to be used when loging in to the vm
236
+ #
237
+ # @return [String]
238
+ attr_accessor :vm_user
239
+
240
+ # The username to be used when loging in to the vm
241
+ #
242
+ # @return [String]
243
+ attr_accessor :vm_password
244
+
245
+ # Private ip for the instance
246
+ #
247
+ # @return [String]
248
+ attr_accessor :private_ip_address
249
+
250
+ # flag to enable/disable expunge vm on destroy
251
+ #
252
+ # @return [Boolean]
253
+ attr_accessor :expunge_on_destroy
254
+
255
+ def initialize(domain_specific=false)
256
+ @host = UNSET_VALUE
257
+ @name = UNSET_VALUE
258
+ @path = UNSET_VALUE
259
+ @port = UNSET_VALUE
260
+ @scheme = UNSET_VALUE
261
+ @api_key = UNSET_VALUE
262
+ @secret_key = UNSET_VALUE
263
+ @instance_ready_timeout = UNSET_VALUE
264
+ @domain_id = UNSET_VALUE
265
+ @network_id = UNSET_VALUE
266
+ @network_name = UNSET_VALUE
267
+ @network_type = UNSET_VALUE
268
+ @project_id = UNSET_VALUE
269
+ @service_offering_id = UNSET_VALUE
270
+ @service_offering_name = UNSET_VALUE
271
+ @template_id = UNSET_VALUE
272
+ @template_name = UNSET_VALUE
273
+ @zone_id = UNSET_VALUE
274
+ @zone_name = UNSET_VALUE
275
+ @keypair = UNSET_VALUE
276
+ @static_nat = UNSET_VALUE
277
+ @pf_ip_address_id = UNSET_VALUE
278
+ @pf_ip_address = UNSET_VALUE
279
+ @pf_public_port = UNSET_VALUE
280
+ @pf_public_rdp_port = UNSET_VALUE
281
+ @pf_private_rdp_port = UNSET_VALUE
282
+ @pf_public_port_randomrange= UNSET_VALUE
283
+ @pf_private_port = UNSET_VALUE
284
+ @pf_open_firewall = UNSET_VALUE
285
+ @pf_trusted_networks = UNSET_VALUE
286
+ @port_forwarding_rules = UNSET_VALUE
287
+ @firewall_rules = UNSET_VALUE
288
+ @security_group_ids = UNSET_VALUE
289
+ @display_name = UNSET_VALUE
290
+ @group = UNSET_VALUE
291
+ @security_group_names = UNSET_VALUE
292
+ @security_groups = UNSET_VALUE
293
+ @user_data = UNSET_VALUE
294
+ @ssh_key = UNSET_VALUE
295
+ @ssh_user = UNSET_VALUE
296
+ @ssh_network_id = UNSET_VALUE
297
+ @ssh_network_name = UNSET_VALUE
298
+ @vm_user = UNSET_VALUE
299
+ @vm_password = UNSET_VALUE
300
+ @private_ip_address = UNSET_VALUE
301
+ @expunge_on_destroy = UNSET_VALUE
302
+
303
+ # Internal state (prefix with __ so they aren't automatically
304
+ # merged)
305
+ @__compiled_domain_configs = {}
306
+ @__finalized = false
307
+ @__domain_config = {}
308
+ @__domain_specific = domain_specific
309
+ end
310
+
311
+ # Allows domain-specific overrides of any of the settings on this
312
+ # configuration object. This allows the user to override things like
313
+ # template and keypair name for domains. Example:
314
+ #
315
+ # cloudstack.domain_config "abcd-ef01-2345-6789" do |domain|
316
+ # domain.template_id = "1234-5678-90ab-cdef"
317
+ # domain.keypair_name = "company-east"
318
+ # end
319
+ #
320
+ # @param [String] domain The Domain name to configure.
321
+ # @param [Hash] attributes Direct attributes to set on the configuration
322
+ # as a shortcut instead of specifying a full block.
323
+ # @yield [config] Yields a new domain configuration.
324
+ def domain_config(domain, attributes=nil, &block)
325
+ # Append the block to the list of domain configs for that domain.
326
+ # We'll evaluate these upon finalization.
327
+ @__domain_config[domain] ||= []
328
+
329
+ # Append a block that sets attributes if we got one
330
+ if attributes
331
+ attr_block = lambda do |config|
332
+ config.set_options(attributes)
333
+ end
334
+
335
+ @__domain_config[domain] << attr_block
336
+ end
337
+
338
+ # Append a block if we got one
339
+ @__domain_config[domain] << block if block_given?
340
+ end
341
+
342
+ #-------------------------------------------------------------------
343
+ # Internal methods.
344
+ #-------------------------------------------------------------------
345
+
346
+ def merge(other)
347
+ super.tap do |result|
348
+ # Copy over the domain specific flag. "True" is retained if either
349
+ # has it.
350
+ new_domain_specific = other.instance_variable_get(:@__domain_specific)
351
+ result.instance_variable_set(
352
+ :@__domain_specific, new_domain_specific || @__domain_specific)
353
+
354
+ # Go through all the domain configs and prepend ours onto
355
+ # theirs.
356
+ new_domain_config = other.instance_variable_get(:@__domain_config)
357
+ @__domain_config.each do |key, value|
358
+ new_domain_config[key] ||= []
359
+ new_domain_config[key] = value + new_domain_config[key]
360
+ end
361
+
362
+ # Set it
363
+ result.instance_variable_set(:@__domain_config, new_domain_config)
364
+
365
+ # Merge in the tags
366
+ result.tags.merge!(self.tags)
367
+ result.tags.merge!(other.tags)
368
+ end
369
+ end
370
+
371
+ def finalize!
372
+ # Host must be nil, since we can't default that
373
+ @host = nil if @host == UNSET_VALUE
374
+
375
+ # Name must be nil, since we can't default that
376
+ @name = nil if @name == UNSET_VALUE
377
+
378
+ # Path must be nil, since we can't default that
379
+ @path = nil if @path == UNSET_VALUE
380
+
381
+ # Port must be nil, since we can't default that
382
+ @port = nil if @port == UNSET_VALUE
383
+
384
+ # We default the scheme to whatever the user has specifid in the .fog file
385
+ # *OR* whatever is default for the provider in the fog library
386
+ @scheme = nil if @scheme == UNSET_VALUE
387
+
388
+ # Try to get access keys from environment variables, they will
389
+ # default to nil if the environment variables are not present
390
+ @api_key = ENV['CLOUDSTACK_API_KEY'] if @api_key == UNSET_VALUE
391
+ @secret_key = ENV['CLOUDSTACK_SECRET_KEY'] if @secret_key == UNSET_VALUE
392
+
393
+ # Set the default timeout for waiting for an instance to be ready
394
+ @instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
395
+
396
+ # Domain id must be nil, since we can't default that
397
+ @domain_id = nil if @domain_id == UNSET_VALUE
398
+
399
+ # Network uuid must be nil, since we can't default that
400
+ @network_id = nil if @network_id == UNSET_VALUE
401
+
402
+ # Network uuid must be nil, since we can't default that
403
+ @network_name = nil if @network_name == UNSET_VALUE
404
+
405
+ # NetworkType is 'Advanced' by default
406
+ @network_type = "Advanced" if @network_type == UNSET_VALUE
407
+
408
+ # Project uuid must be nil, since we can't default that
409
+ @project_id = nil if @project_id == UNSET_VALUE
410
+
411
+ # Service offering uuid must be nil, since we can't default that
412
+ @service_offering_id = nil if @service_offering_id == UNSET_VALUE
413
+
414
+ # Service offering name must be nil, since we can't default that
415
+ @service_offering_name = nil if @service_offering_name == UNSET_VALUE
416
+
417
+ # Template uuid must be nil, since we can't default that
418
+ @template_id = nil if @template_id == UNSET_VALUE
419
+
420
+ # Template name must be nil, since we can't default that
421
+ @template_name = nil if @template_name == UNSET_VALUE
422
+
423
+ # Zone uuid must be nil, since we can't default that
424
+ @zone_id = nil if @zone_id == UNSET_VALUE
425
+
426
+ # Zone uuid must be nil, since we can't default that
427
+ @zone_name = nil if @zone_name == UNSET_VALUE
428
+
429
+ # Keypair defaults to nil
430
+ @keypair = nil if @keypair == UNSET_VALUE
431
+
432
+ # Static NAT must be empty array
433
+ @static_nat = [] if @static_nat == UNSET_VALUE
434
+
435
+ # IP address id must be nil, since we can't default that
436
+ @pf_ip_address_id = nil if @pf_ip_address_id == UNSET_VALUE
437
+
438
+ # IP address must be nil, since we can't default that
439
+ @pf_ip_address = nil if @pf_ip_address == UNSET_VALUE
440
+
441
+ # Public port must be nil, since we can't default that
442
+ @pf_public_port = nil if @pf_public_port == UNSET_VALUE
443
+
444
+ # Public port must be nil, since we can't default that
445
+ @pf_public_rdp_port = nil if @pf_public_rdp_port == UNSET_VALUE
446
+
447
+ # Private rdp port defaults to 3389
448
+ @pf_private_rdp_port = 3389 if @pf_private_rdp_port == UNSET_VALUE
449
+
450
+ # Public port random-range, default to rfc6335 'Dynamic Ports'; "(never assigned)"
451
+ @pf_public_port_randomrange = {:start=>49160, :end=>49200} if @pf_public_port_randomrange == UNSET_VALUE
452
+
453
+ # Private port must be nil, since we can't default that
454
+ @pf_private_port = nil if @pf_private_port == UNSET_VALUE
455
+
456
+ # Open firewall is true by default (for backwards compatibility)
457
+ @pf_open_firewall = true if @pf_open_firewall == UNSET_VALUE
458
+
459
+ # Trusted networks must be nil, since we can't default that
460
+ @pf_trusted_networks = nil if @pf_trusted_networks == UNSET_VALUE
461
+
462
+ # Port forwarding rules must be empty array
463
+ @port_forwarding_rules = [] if @port_forwarding_rules == UNSET_VALUE
464
+
465
+ # Firewall rules must be empty array
466
+ @firewall_rules = [] if @firewall_rules == UNSET_VALUE
467
+
468
+ # Security Group IDs must be nil, since we can't default that
469
+ @security_group_ids = [] if @security_group_ids == UNSET_VALUE
470
+
471
+ # Security Group Names must be nil, since we can't default that
472
+ @security_group_names = [] if @security_group_names == UNSET_VALUE
473
+
474
+ # Security Groups must be nil, since we can't default that
475
+ @security_groups = [] if @security_groups == UNSET_VALUE
476
+
477
+ # Display name must be nil, since we can't default that
478
+ @display_name = nil if @display_name == UNSET_VALUE
479
+
480
+ # Group must be nil, since we can't default that
481
+ @group = nil if @group == UNSET_VALUE
482
+
483
+ # User Data is nil by default
484
+ @user_data = nil if @user_data == UNSET_VALUE
485
+
486
+ # ssh key is nil by default
487
+ @ssh_key = nil if @ssh_key == UNSET_VALUE
488
+
489
+ # ssh user is nil by default
490
+ @ssh_user = nil if @ssh_user == UNSET_VALUE
491
+
492
+ # ssh network_id is nil by default
493
+ @ssh_network_id = nil if @ssh_network_id == UNSET_VALUE
494
+
495
+ # ssh network_name is nil by default
496
+ @ssh_network_name = nil if @ssh_network_name == UNSET_VALUE
497
+
498
+ # vm user is nil by default
499
+ @vm_user = nil if @vm_user == UNSET_VALUE
500
+
501
+ # vm password is nil by default
502
+ @vm_password = nil if @vm_password == UNSET_VALUE
503
+
504
+ # private ip is nil by default
505
+ @private_ip_address = nil if @private_ip_address == UNSET_VALUE
506
+
507
+ # expunge on destroy is nil by default
508
+ @expunge_on_destroy = false if @expunge_on_destroy == UNSET_VALUE
509
+
510
+ # Compile our domain specific configurations only within
511
+ # NON-DOMAIN-SPECIFIC configurations.
512
+ if !@__domain_specific
513
+ @__domain_config.each do |domain, blocks|
514
+ config = self.class.new(true).merge(self)
515
+
516
+ # Execute the configuration for each block
517
+ blocks.each { |b| b.call(config) }
518
+
519
+ # The domain name of the configuration always equals the
520
+ # domain config name:
521
+ config.domain = domain
522
+
523
+ # Finalize the configuration
524
+ config.finalize!
525
+
526
+ # Store it for retrieval
527
+ @__compiled_domain_configs[domain] = config
528
+ end
529
+ end
530
+
531
+ # Mark that we finalized
532
+ @__finalized = true
533
+ end
534
+
535
+ def validate(machine)
536
+ errors = []
537
+
538
+ if @domain
539
+ # Get the configuration for the domain we're using and validate only
540
+ # that domain.
541
+ config = get_domain_config(@domain)
542
+
543
+ if !config.use_fog_profile
544
+ errors << I18n.t("vagrant_cloudstack.config.api_key_required") if \
545
+ config.access_key_id.nil?
546
+ errors << I18n.t("vagrant_cloudstack.config.secret_key_required") if \
547
+ config.secret_access_key.nil?
548
+ end
549
+ end
550
+
551
+ {"Cloudstack Provider" => errors}
552
+ end
553
+
554
+ # This gets the configuration for a specific domain. It shouldn't
555
+ # be called by the general public and is only used internally.
556
+ def get_domain_config(name)
557
+ if !@__finalized
558
+ raise "Configuration must be finalized before calling this method."
559
+ end
560
+
561
+ # Return the compiled domain config
562
+ @__compiled_domain_configs[name] || self
563
+ end
564
+ end
565
+ end
566
+ end