fog 0.3.16 → 0.3.17

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 (112) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.rdoc +17 -12
  3. data/fog.gemspec +10 -5
  4. data/lib/fog.rb +1 -1
  5. data/lib/fog/aws/models/storage/directory.rb +22 -0
  6. data/lib/fog/aws/models/storage/file.rb +15 -0
  7. data/lib/fog/aws/storage.rb +8 -0
  8. data/lib/fog/core/collection.rb +9 -8
  9. data/lib/fog/core/compute.rb +1 -1
  10. data/lib/fog/google/models/storage/directory.rb +23 -1
  11. data/lib/fog/google/models/storage/file.rb +16 -1
  12. data/lib/fog/google/parsers/storage/access_control_list.rb +16 -14
  13. data/lib/fog/local/models/storage/directory.rb +8 -0
  14. data/lib/fog/local/models/storage/file.rb +4 -0
  15. data/lib/fog/rackspace/cdn.rb +3 -3
  16. data/lib/fog/rackspace/models/storage/directory.rb +18 -0
  17. data/lib/fog/rackspace/models/storage/file.rb +7 -0
  18. data/lib/fog/rackspace/requests/cdn/{get_cdn_containers.rb → get_containers.rb} +3 -3
  19. data/lib/fog/rackspace/requests/cdn/{head_cdn_container.rb → head_container.rb} +3 -3
  20. data/lib/fog/rackspace/requests/cdn/{put_cdn_container.rb → put_container.rb} +3 -3
  21. data/lib/fog/rackspace/storage.rb +10 -0
  22. data/lib/fog/vcloud.rb +32 -153
  23. data/lib/fog/vcloud/collection.rb +18 -0
  24. data/lib/fog/vcloud/mock_data_classes.rb +701 -0
  25. data/lib/fog/vcloud/requests/get_network.rb +8 -8
  26. data/lib/fog/vcloud/requests/get_organization.rb +10 -10
  27. data/lib/fog/vcloud/requests/get_vdc.rb +18 -18
  28. data/lib/fog/vcloud/requests/get_versions.rb +3 -3
  29. data/lib/fog/vcloud/requests/login.rb +2 -2
  30. data/lib/fog/vcloud/terremark/ecloud.rb +65 -109
  31. data/lib/fog/vcloud/terremark/ecloud/models/catalog.rb +1 -0
  32. data/lib/fog/vcloud/terremark/ecloud/models/firewall_acls.rb +1 -0
  33. data/lib/fog/vcloud/terremark/ecloud/models/internet_services.rb +1 -0
  34. data/lib/fog/vcloud/terremark/ecloud/models/ip.rb +1 -1
  35. data/lib/fog/vcloud/terremark/ecloud/models/ips.rb +1 -0
  36. data/lib/fog/vcloud/terremark/ecloud/models/network.rb +3 -2
  37. data/lib/fog/vcloud/terremark/ecloud/models/networks.rb +1 -0
  38. data/lib/fog/vcloud/terremark/ecloud/models/nodes.rb +1 -0
  39. data/lib/fog/vcloud/terremark/ecloud/models/public_ips.rb +1 -0
  40. data/lib/fog/vcloud/terremark/ecloud/models/server.rb +20 -8
  41. data/lib/fog/vcloud/terremark/ecloud/models/servers.rb +1 -0
  42. data/lib/fog/vcloud/terremark/ecloud/models/tasks.rb +1 -0
  43. data/lib/fog/vcloud/terremark/ecloud/models/vdcs.rb +2 -0
  44. data/lib/fog/vcloud/terremark/ecloud/requests/add_internet_service.rb +4 -8
  45. data/lib/fog/vcloud/terremark/ecloud/requests/add_node.rb +4 -7
  46. data/lib/fog/vcloud/terremark/ecloud/requests/configure_internet_service.rb +18 -20
  47. data/lib/fog/vcloud/terremark/ecloud/requests/configure_node.rb +6 -7
  48. data/lib/fog/vcloud/terremark/ecloud/requests/configure_vapp.rb +40 -9
  49. data/lib/fog/vcloud/terremark/ecloud/requests/delete_internet_service.rb +2 -10
  50. data/lib/fog/vcloud/terremark/ecloud/requests/delete_node.rb +2 -6
  51. data/lib/fog/vcloud/terremark/ecloud/requests/delete_vapp.rb +13 -1
  52. data/lib/fog/vcloud/terremark/ecloud/requests/get_catalog.rb +6 -6
  53. data/lib/fog/vcloud/terremark/ecloud/requests/get_catalog_item.rb +6 -7
  54. data/lib/fog/vcloud/terremark/ecloud/requests/get_internet_services.rb +34 -33
  55. data/lib/fog/vcloud/terremark/ecloud/requests/get_network.rb +23 -24
  56. data/lib/fog/vcloud/terremark/ecloud/requests/get_network_extensions.rb +10 -13
  57. data/lib/fog/vcloud/terremark/ecloud/requests/get_network_ip.rb +15 -19
  58. data/lib/fog/vcloud/terremark/ecloud/requests/get_network_ips.rb +20 -22
  59. data/lib/fog/vcloud/terremark/ecloud/requests/get_node.rb +12 -15
  60. data/lib/fog/vcloud/terremark/ecloud/requests/get_nodes.rb +11 -12
  61. data/lib/fog/vcloud/terremark/ecloud/requests/get_public_ip.rb +5 -4
  62. data/lib/fog/vcloud/terremark/ecloud/requests/get_public_ips.rb +9 -8
  63. data/lib/fog/vcloud/terremark/ecloud/requests/get_vapp.rb +33 -17
  64. data/lib/fog/vcloud/terremark/ecloud/requests/get_vdc.rb +54 -53
  65. data/lib/fog/vcloud/terremark/ecloud/requests/instantiate_vapp_template.rb +13 -19
  66. data/lib/fog/vcloud/terremark/ecloud/requests/power_off.rb +9 -2
  67. data/lib/fog/vcloud/terremark/ecloud/requests/power_on.rb +2 -4
  68. data/spec/vcloud/bin_spec.rb +3 -6
  69. data/spec/vcloud/models/vdc_spec.rb +8 -8
  70. data/spec/vcloud/requests/get_network_spec.rb +8 -8
  71. data/spec/vcloud/requests/get_organization_spec.rb +9 -9
  72. data/spec/vcloud/requests/get_vdc_spec.rb +7 -7
  73. data/spec/vcloud/requests/get_versions_spec.rb +1 -1
  74. data/spec/vcloud/requests/login_spec.rb +2 -2
  75. data/spec/vcloud/spec_helper.rb +45 -30
  76. data/spec/vcloud/terremark/ecloud/models/internet_service_spec.rb +10 -14
  77. data/spec/vcloud/terremark/ecloud/models/ip_spec.rb +5 -8
  78. data/spec/vcloud/terremark/ecloud/models/ips_spec.rb +2 -2
  79. data/spec/vcloud/terremark/ecloud/models/network_spec.rb +15 -16
  80. data/spec/vcloud/terremark/ecloud/models/node_spec.rb +7 -7
  81. data/spec/vcloud/terremark/ecloud/models/nodes_spec.rb +1 -1
  82. data/spec/vcloud/terremark/ecloud/models/public_ip_spec.rb +4 -8
  83. data/spec/vcloud/terremark/ecloud/models/server_spec.rb +42 -0
  84. data/spec/vcloud/terremark/ecloud/models/vdc_spec.rb +7 -7
  85. data/spec/vcloud/terremark/ecloud/models/vdcs_spec.rb +1 -1
  86. data/spec/vcloud/terremark/ecloud/requests/add_internet_service_spec.rb +13 -18
  87. data/spec/vcloud/terremark/ecloud/requests/add_node_spec.rb +9 -5
  88. data/spec/vcloud/terremark/ecloud/requests/configure_internet_service_spec.rb +5 -7
  89. data/spec/vcloud/terremark/ecloud/requests/configure_node_spec.rb +22 -28
  90. data/spec/vcloud/terremark/ecloud/requests/configure_vapp_spec.rb +71 -0
  91. data/spec/vcloud/terremark/ecloud/requests/delete_internet_service_spec.rb +7 -9
  92. data/spec/vcloud/terremark/ecloud/requests/delete_node_spec.rb +3 -7
  93. data/spec/vcloud/terremark/ecloud/requests/delete_vapp_spec.rb +83 -0
  94. data/spec/vcloud/terremark/ecloud/requests/get_catalog_item_spec.rb +6 -5
  95. data/spec/vcloud/terremark/ecloud/requests/get_catalog_spec.rb +2 -2
  96. data/spec/vcloud/terremark/ecloud/requests/get_internet_services_spec.rb +31 -42
  97. data/spec/vcloud/terremark/ecloud/requests/get_network_ip_spec.rb +4 -7
  98. data/spec/vcloud/terremark/ecloud/requests/get_network_ips_spec.rb +1 -1
  99. data/spec/vcloud/terremark/ecloud/requests/get_network_spec.rb +19 -11
  100. data/spec/vcloud/terremark/ecloud/requests/get_node_spec.rb +8 -8
  101. data/spec/vcloud/terremark/ecloud/requests/get_nodes_spec.rb +11 -11
  102. data/spec/vcloud/terremark/ecloud/requests/get_public_ip_spec.rb +4 -5
  103. data/spec/vcloud/terremark/ecloud/requests/get_public_ips_spec.rb +6 -6
  104. data/spec/vcloud/terremark/ecloud/requests/get_vapp_spec.rb +36 -19
  105. data/spec/vcloud/terremark/ecloud/requests/get_vdc_spec.rb +21 -18
  106. data/spec/vcloud/terremark/ecloud/requests/instantiate_vapp_template_spec.rb +27 -17
  107. data/spec/vcloud/terremark/ecloud/requests/power_off_spec.rb +34 -0
  108. data/spec/vcloud/terremark/ecloud/requests/power_on_spec.rb +3 -4
  109. data/spec/vcloud/vcloud_spec.rb +2 -2
  110. data/tests/helpers/storage/directory_tests.rb +8 -0
  111. data/tests/helpers/storage/file_tests.rb +4 -0
  112. metadata +11 -6
@@ -1,6 +1,6 @@
1
1
  module Fog
2
2
  module Rackspace
3
- class Storage
3
+ class CDN
4
4
  class Real
5
5
 
6
6
  # List cdn properties for a container
@@ -17,7 +17,7 @@ module Fog
17
17
  # * 'X-Log-Retention'<~Boolean> - ?
18
18
  # * 'X-User-Agent-ACL'<~String> - ?
19
19
  # * 'X-Referrer-ACL'<~String> - ?
20
- def head_cdn_container(container)
20
+ def head_container(container)
21
21
  response = request(
22
22
  :expects => 204,
23
23
  :method => 'HEAD',
@@ -31,7 +31,7 @@ module Fog
31
31
 
32
32
  class Mock
33
33
 
34
- def head_cdn_container(container)
34
+ def head_container(container)
35
35
  Fog::Mock.not_implemented
36
36
  end
37
37
 
@@ -1,6 +1,6 @@
1
1
  module Fog
2
2
  module Rackspace
3
- class Storage
3
+ class CDN
4
4
  class Real
5
5
 
6
6
  # modify CDN properties for a container
@@ -14,7 +14,7 @@ module Fog
14
14
  # * 'X-Log-Retention'<~Boolean> - ?
15
15
  # * 'X-User-Agent-ACL'<~String> - ?
16
16
  # * 'X-Referrer-ACL'<~String> - ?
17
- def put_cdn_container(name, options = {})
17
+ def put_container(name, options = {})
18
18
  response = request(
19
19
  :expects => [201, 202],
20
20
  :headers => options,
@@ -28,7 +28,7 @@ module Fog
28
28
 
29
29
  class Mock
30
30
 
31
- def put_cdn_container(name, options = {})
31
+ def put_container(name, options = {})
32
32
  Fog::Mock.not_implemented
33
33
  end
34
34
 
@@ -24,6 +24,13 @@ module Fog
24
24
 
25
25
  module Utils
26
26
 
27
+ def cdn
28
+ @cdn ||= Fog::Rackspace::CDN.new(
29
+ :rackspace_api_key => @rackspace_api_key,
30
+ :rackspace_username => @rackspace_username
31
+ )
32
+ end
33
+
27
34
  def parse_data(data)
28
35
  metadata = {
29
36
  :body => nil,
@@ -64,6 +71,7 @@ module Fog
64
71
 
65
72
  def initialize(options={})
66
73
  require 'mime/types'
74
+ @rackspace_api_key = options[:rackspace_api_key]
67
75
  @rackspace_username = options[:rackspace_username]
68
76
  @data = self.class.data[@rackspace_username]
69
77
  end
@@ -76,6 +84,8 @@ module Fog
76
84
  def initialize(options={})
77
85
  require 'mime/types'
78
86
  require 'json'
87
+ @rackspace_api_key = options[:rackspace_api_key]
88
+ @rackspace_username = options[:rackspace_username]
79
89
  credentials = Fog::Rackspace.authenticate(options)
80
90
  @auth_token = credentials['X-Auth-Token']
81
91
 
@@ -5,6 +5,7 @@ require 'builder'
5
5
  require 'fog/vcloud/model'
6
6
  require 'fog/vcloud/collection'
7
7
  require 'fog/vcloud/generators'
8
+ require 'fog/vcloud/mock_data_classes'
8
9
  # ecloud/vcloud requires at the bottom so that the following will be defined
9
10
 
10
11
  module URI
@@ -249,6 +250,7 @@ module Fog
249
250
 
250
251
  class Mock
251
252
  include Shared
253
+ include MockDataClasses
252
254
 
253
255
  def self.base_url
254
256
  "https://fakey.com/api/v0.8"
@@ -259,159 +261,36 @@ module Fog
259
261
  end
260
262
 
261
263
  def self.data( base_url = self.base_url )
262
- @mock_data ||=
263
- {
264
- :versions => [
265
- { :version => "v0.8", :login_url => "#{base_url}/login", :supported => true }
266
- ],
267
- :vdc_resources => [
268
- {
269
- :type => "application/vnd.vmware.vcloud.vApp+xml",
270
- :href => "#{base_url}/vapp/61",
271
- :name => "Foo App 1"
272
- },
273
- {
274
- :type => "application/vnd.vmware.vcloud.vApp+xml",
275
- :href => "#{base_url}/vapp/62",
276
- :name => "Bar App 1"
277
- },
278
- {
279
- :type => "application/vnd.vmware.vcloud.vApp+xml",
280
- :href => "#{base_url}/vapp/63",
281
- :name => "Bar App 2"
282
- }
283
- ],
284
- :organizations =>
285
- [
286
- {
287
- :info => {
288
- :href => "#{base_url}/org/1",
289
- :name => "Boom Inc.",
290
- },
291
- :vdcs => [
292
-
293
- { :href => "#{base_url}/vdc/21",
294
- :id => "21",
295
- :name => "Boomstick",
296
- :storage => { :used => "105", :allocated => "200" },
297
- :cpu => { :allocated => "10000" },
298
- :memory => { :allocated => "20480" },
299
- :catalog => {
300
- :name => "The catalog",
301
- :items => [
302
- { :id => "0", :name => "Item 0", :disks => [{ :size => 25 }] },
303
- { :id => "1", :name => "Item 1" },
304
- { :id => "2", :name => "Item 2" },
305
- ]
306
- },
307
- :networks => [
308
- { :id => "31",
309
- :href => "#{base_url}/network/31",
310
- :name => "1.2.3.0/24",
311
- :subnet => "1.2.3.0/24",
312
- :gateway => "1.2.3.1",
313
- :netmask => "255.255.255.0",
314
- :dns => "8.8.8.8",
315
- :features => [
316
- { :type => :FenceMode, :value => "isolated" }
317
- ],
318
- :ips => { "1.2.3.3" => "Broom 1", "1.2.3.4" => "Broom 2", "1.2.3.10" => "Email" }
319
- },
320
- { :id => "32",
321
- :href => "#{base_url}/network/32",
322
- :name => "4.5.6.0/24",
323
- :subnet => "4.5.6.0/24",
324
- :gateway => "4.5.6.1",
325
- :netmask => "255.255.255.0",
326
- :dns => "8.8.8.8",
327
- :features => [
328
- { :type => :FenceMode, :value => "isolated" }
329
- ],
330
- :ips => { }
331
- },
332
- ],
333
- :vms => [
334
- { :href => "#{base_url}/vapp/41",
335
- :name => "Broom 1",
336
- :ip => "1.2.3.3",
337
- :memory => 1024,
338
- :cpus => 1,
339
- :disks => [{ :size => 25 }],
340
- :status => 2
341
- },
342
- { :href => "#{base_url}/vapp/42",
343
- :name => "Broom 2",
344
- :ip => "1.2.3.4"
345
- },
346
- { :href => "#{base_url}/vapp/43",
347
- :name => "Email!"
348
- }
349
- ]
350
- },
351
- { :href => "#{base_url}/vdc/22",
352
- :id => "22",
353
- :storage => { :used => "40", :allocated => "150" },
354
- :cpu => { :allocated => "1000" },
355
- :memory => { :allocated => "2048" },
356
- :name => "Rock-n-Roll",
357
- :networks => [
358
- { :id => "33",
359
- :href => "#{base_url}/network/33",
360
- :name => "7.8.9.0/24",
361
- :subnet => "7.8.9.0/24",
362
- :gateway => "7.8.9.1",
363
- :dns => "8.8.8.8",
364
- :netmask => "255.255.255.0",
365
- :features => [
366
- { :type => :FenceMode, :value => "isolated" }
367
- ],
368
- :ips => { "7.8.9.10" => "Master Blaster" }
369
- }
370
- ],
371
- :vms => [
372
- { :href => "#{base_url}/vapp/44",
373
- :name => "Master Blaster"
374
- }
375
- ]
376
- }
377
- ]
378
- }
379
- ]
380
- }
381
- end
382
-
383
- def vdc_from_uri(uri)
384
- match = Regexp.new(%r:.*/vdc/(\d+):).match(uri.to_s)
385
- match && vdc_from_id(match[1])
386
- end
387
-
388
- def vdc_from_id(id)
389
- mock_data[:organizations].map { |org| org[:vdcs] }.flatten.detect { |vdc| vdc[:id] == id }
390
- end
391
-
392
- def ip_from_uri(uri)
393
- match = Regexp.new(%r:.*/publicIp/(\d+):).match(uri.to_s)
394
- if match
395
- mock_data[:organizations].map { |org| org[:vdcs] }.flatten.map { |vdc| vdc[:public_ips] }.flatten.compact.detect { |public_ip| public_ip[:id] == match[1] }
396
- end
397
- end
398
-
399
- def vapp_and_vdc_from_vapp_uri(uri)
400
- if vdc = mock_data[:organizations].map {|o| o[:vdcs] }.flatten.detect {|vd| vd[:vms].detect {|vm| uri =~ %r{^#{Regexp.escape(vm[:href])}($|/)} } }
401
- vapp = vdc[:vms].detect {|v| uri =~ %r{^#{Regexp.escape(v[:href])}($|/)} }
402
- if vapp
403
- [vapp, vdc]
404
- end
405
- end
406
- end
407
-
408
- def catalog_item_and_vdc_from_catalog_item_uri(uri)
409
- catalog_item_id, vdc_id = uri.split("/").last.split("-")
410
- vdc = vdc_from_id(vdc_id)
411
- if vdc
412
- catalog_item = vdc[:catalog][:items].detect {|ci| ci[:id] == catalog_item_id }
413
- if catalog_item
414
- [catalog_item, vdc]
264
+ MockDataClasses::Base.base_url = base_url
265
+
266
+ @mock_data ||= MockData.new.tap do |mock_data|
267
+ mock_data.versions << MockVersion.new(:version => "v0.8", :supported => true)
268
+
269
+ mock_data.organizations << MockOrganization.new(:name => "Boom Inc.").tap do |mock_organization|
270
+ mock_organization.vdcs << MockVdc.new(:name => "Boomstick").tap do |mock_vdc|
271
+ mock_vdc.catalog.items << MockCatalogItem.new(:name => "Item 0").tap do |mock_catalog_item|
272
+ mock_catalog_item.disks << MockVirtualMachineDisk.new(:size => 25 * 1024)
273
+ end
274
+ mock_vdc.catalog.items << MockCatalogItem.new(:name => "Item 1").tap do |mock_catalog_item|
275
+ mock_catalog_item.disks << MockVirtualMachineDisk.new(:size => 25 * 1024)
276
+ end
277
+ mock_vdc.catalog.items << MockCatalogItem.new(:name => "Item 2").tap do |mock_catalog_item|
278
+ mock_catalog_item.disks << MockVirtualMachineDisk.new(:size => 25 * 1024)
279
+ end
280
+
281
+ mock_vdc.networks << MockNetwork.new({ :subnet => "1.2.3.0/24" }, mock_vdc)
282
+ mock_vdc.networks << MockNetwork.new({ :subnet => "4.5.6.0/24" }, mock_vdc)
283
+
284
+ mock_vdc.virtual_machines << MockVirtualMachine.new({ :name => "Broom 1", :ip => "1.2.3.3" }, mock_vdc)
285
+ mock_vdc.virtual_machines << MockVirtualMachine.new({ :name => "Broom 2", :ip => "1.2.3.4" }, mock_vdc)
286
+ mock_vdc.virtual_machines << MockVirtualMachine.new({ :name => "Email!", :ip => "1.2.3.10" }, mock_vdc)
287
+ end
288
+
289
+ mock_organization.vdcs << MockVdc.new(:name => "Rock-n-Roll", :storage_allocated => 150, :storage_used => 40, :cpu_allocated => 1000, :memory_allocated => 2048).tap do |mock_vdc|
290
+ mock_vdc.networks << MockNetwork.new({ :subnet => "7.8.9.0/24" }, mock_vdc)
291
+
292
+ mock_vdc.virtual_machines << MockVirtualMachine.new({ :name => "Master Blaster", :ip => "7.8.9.10" }, mock_vdc)
293
+ end
415
294
  end
416
295
  end
417
296
  end
@@ -7,6 +7,24 @@ module Fog
7
7
  super
8
8
  end
9
9
 
10
+ def check_href!(opts = {})
11
+ unless href
12
+ if opts.is_a?(String)
13
+ t = Hash.new
14
+ t[:parent] = opts
15
+ opts = t
16
+ end
17
+ msg = ":href missing, call with a :href pointing to #{if opts[:message]
18
+ opts[:message]
19
+ elsif opts[:parent]
20
+ "the #{opts[:parent]} whos #{self.class.to_s.split('::').last.downcase} you want to enumerate"
21
+ else
22
+ "the resource"
23
+ end}"
24
+ raise Fog::Errors::Error.new(msg)
25
+ end
26
+ end
27
+
10
28
  end
11
29
  end
12
30
  end
@@ -0,0 +1,701 @@
1
+ require "ipaddr"
2
+
3
+ class IPAddr
4
+ def mask
5
+ _to_string(@mask_addr)
6
+ end
7
+ end
8
+
9
+ module Fog
10
+ class Vcloud
11
+ module MockDataClasses
12
+ class Base < Hash
13
+ def self.base_url=(url)
14
+ @base_url = url
15
+ end
16
+
17
+ self.base_url = "http://vcloud.example.com"
18
+
19
+ def self.base_url
20
+ @base_url
21
+ end
22
+
23
+ def first
24
+ raise "Don't do this"
25
+ end
26
+
27
+ def last
28
+ raise "Don't do this"
29
+ end
30
+
31
+ def initialize(data = {}, parent = nil)
32
+ @parent = parent
33
+
34
+ replace(data)
35
+ end
36
+
37
+ def _parent
38
+ @parent
39
+ end
40
+
41
+ def base_url
42
+ Base.base_url
43
+ end
44
+
45
+ def href
46
+ [base_url, self.class.name.split("::").last, object_id].join("/")
47
+ end
48
+
49
+ def inspect
50
+ "<#{self.class.name} #{object_id} data=#{super} method_data=#{method_data.inspect}>"
51
+ end
52
+
53
+ private
54
+
55
+ def unique_methods
56
+ (public_methods - self.class.superclass.public_instance_methods).reject {|m| m.to_s =~ /!$/ }
57
+ end
58
+
59
+ def method_data
60
+ (unique_methods + [:href]).sort_by(&:to_s).find_all {|m| method(m).arity == 0 }.inject({}) {|md, m| md.update(m => send(m)) }
61
+ end
62
+ end
63
+
64
+ class MockData < Base
65
+ def versions
66
+ @versions ||= []
67
+ end
68
+
69
+ def organizations
70
+ @organizations ||= []
71
+ end
72
+
73
+ def organization_from_href(href)
74
+ find_href_in(href, organizations)
75
+ end
76
+
77
+ def all_vdcs
78
+ organizations.map(&:vdcs).flatten
79
+ end
80
+
81
+ def vdc_from_href(href)
82
+ find_href_in(href, all_vdcs)
83
+ end
84
+
85
+ def all_catalogs
86
+ all_vdcs.map(&:catalog).flatten
87
+ end
88
+
89
+ def catalog_from_href(href)
90
+ find_href_in(href, all_catalogs)
91
+ end
92
+
93
+ def all_catalog_items
94
+ all_catalogs.map(&:items).flatten
95
+ end
96
+
97
+ def catalog_item_from_href(href)
98
+ find_href_in(href, all_catalog_items)
99
+ end
100
+
101
+ def all_virtual_machines
102
+ all_vdcs.map(&:virtual_machines).flatten
103
+ end
104
+
105
+ def virtual_machine_from_href(href)
106
+ find_href_prefixed_in(href, all_virtual_machines)
107
+ end
108
+
109
+
110
+ def all_networks
111
+ all_vdcs.map(&:networks).flatten
112
+ end
113
+
114
+ def network_from_href(href)
115
+ find_href_in(href, all_networks)
116
+ end
117
+
118
+ def all_network_extensions
119
+ all_networks.map(&:extensions).flatten
120
+ end
121
+
122
+ def network_extension_from_href(href)
123
+ find_href_in(href, all_network_extensions)
124
+ end
125
+
126
+ def all_vdc_internet_service_collections
127
+ all_vdcs.map(&:internet_service_collection).flatten
128
+ end
129
+
130
+ def vdc_internet_service_collection_from_href(href)
131
+ find_href_in(href, all_vdc_internet_service_collections)
132
+ end
133
+
134
+ def all_public_ip_collections
135
+ all_vdcs.map {|v| v.public_ip_collection }.flatten
136
+ end
137
+
138
+ def public_ip_collection_from_href(href)
139
+ find_href_in(href, all_public_ip_collections)
140
+ end
141
+
142
+ def all_public_ips
143
+ all_public_ip_collections.map(&:items).flatten
144
+ end
145
+
146
+ def public_ip_from_href(href)
147
+ find_href_in(href, all_public_ips)
148
+ end
149
+
150
+ def all_public_ip_internet_service_collections
151
+ all_public_ips.map(&:internet_service_collection).flatten
152
+ end
153
+
154
+ def public_ip_internet_service_collection_from_href(href)
155
+ find_href_in(href, all_public_ip_internet_service_collections)
156
+ end
157
+
158
+ def all_public_ip_internet_services
159
+ all_public_ip_internet_service_collections.map(&:items).flatten
160
+ end
161
+
162
+ def public_ip_internet_service_from_href(href)
163
+ find_href_in(href, all_public_ip_internet_services)
164
+ end
165
+
166
+ def all_public_ip_internet_service_node_collections
167
+ all_public_ip_internet_services.map(&:node_collection).flatten
168
+ end
169
+
170
+ def public_ip_internet_service_node_collection_from_href(href)
171
+ find_href_in(href, all_public_ip_internet_service_node_collections)
172
+ end
173
+
174
+ def all_public_ip_internet_service_nodes
175
+ all_public_ip_internet_service_node_collections.map(&:items).flatten
176
+ end
177
+
178
+ def public_ip_internet_service_node_from_href(href)
179
+ find_href_in(href, all_public_ip_internet_service_nodes)
180
+ end
181
+
182
+ def all_network_ip_collections
183
+ all_networks.map(&:ip_collection)
184
+ end
185
+
186
+ def network_ip_collection_from_href(href)
187
+ find_href_in(href, all_network_ip_collections)
188
+ end
189
+
190
+ def all_network_ips
191
+ all_network_ip_collections.map {|c| c.items.values }.flatten
192
+ end
193
+
194
+ def network_ip_from_href(href)
195
+ find_href_in(href, all_network_ips)
196
+ end
197
+
198
+ private
199
+
200
+ def find_href_in(href, objects)
201
+ objects.detect {|o| o.href == href }
202
+ end
203
+
204
+ def find_href_prefixed_in(href, objects)
205
+ objects.detect {|o| href =~ %r{^#{o.href}($|/)} }
206
+ end
207
+ end
208
+
209
+ class MockVersion < Base
210
+ def version
211
+ self[:version]
212
+ end
213
+
214
+ def supported
215
+ !!self[:supported]
216
+ end
217
+
218
+ def login_url
219
+ href
220
+ end
221
+ end
222
+
223
+ class MockOrganization < Base
224
+ def name
225
+ self[:name]
226
+ end
227
+
228
+ def vdcs
229
+ @vdcs ||= []
230
+ end
231
+ end
232
+
233
+ class MockVdc < Base
234
+ def name
235
+ self[:name]
236
+ end
237
+
238
+ def storage_allocated
239
+ self[:storage_allocated] || 200
240
+ end
241
+
242
+ def storage_used
243
+ self[:storage_used] || 105
244
+ end
245
+
246
+ def cpu_allocated
247
+ self[:cpu_allocated] || 10000
248
+ end
249
+
250
+ def memory_allocated
251
+ self[:memory_allocated] || 20480
252
+ end
253
+
254
+ def catalog
255
+ @catalog ||= MockCatalog.new({}, self)
256
+ end
257
+
258
+ def networks
259
+ @networks ||= []
260
+ end
261
+
262
+ def virtual_machines
263
+ @virtual_machines ||= []
264
+ end
265
+
266
+ def task_list
267
+ @task_list ||= MockTaskList.new({}, self)
268
+ end
269
+
270
+ # for TM eCloud, should probably be subclassed
271
+ def public_ip_collection
272
+ @public_ip_collection ||= MockPublicIps.new({}, self)
273
+ end
274
+
275
+ def internet_service_collection
276
+ @internet_service_collection ||= MockVdcInternetServices.new({}, self)
277
+ end
278
+
279
+ def firewall_acls
280
+ @firewall_acls ||= MockFirewallAcls.new({}, self)
281
+ end
282
+ end
283
+
284
+ class MockTaskList < Base
285
+ def name
286
+ self[:name] || "Tasks List"
287
+ end
288
+ end
289
+
290
+ class MockCatalog < Base
291
+ def name
292
+ self[:name] || "Catalog"
293
+ end
294
+
295
+ def items
296
+ @items ||= []
297
+ end
298
+ end
299
+
300
+ class MockCatalogItem < Base
301
+ def name
302
+ self[:name]
303
+ end
304
+
305
+ def disks
306
+ @disks ||= MockVirtualMachineDisks.new(self)
307
+ end
308
+
309
+ def customization
310
+ @customization ||= MockCatalogItemCustomization.new({}, self)
311
+ end
312
+
313
+ def vapp_template
314
+ @vapp_template ||= MockCatalogItemVappTemplate.new({ :name => name }, self)
315
+ end
316
+ end
317
+
318
+ class MockCatalogItemCustomization < Base
319
+ def name
320
+ self[:name] || "Customization Options"
321
+ end
322
+ end
323
+
324
+ class MockCatalogItemVappTemplate < Base
325
+ def name
326
+ self[:name]
327
+ end
328
+ end
329
+
330
+ class MockNetwork < Base
331
+ def name
332
+ self[:name] || subnet
333
+ end
334
+
335
+ def subnet
336
+ self[:subnet]
337
+ end
338
+
339
+ def gateway
340
+ self[:gateway] || subnet_ips[1]
341
+ end
342
+
343
+ def netmask
344
+ self[:netmask] || subnet_ipaddr.mask
345
+ end
346
+
347
+ def dns
348
+ "8.8.8.8"
349
+ end
350
+
351
+ def features
352
+ [
353
+ { :type => :FenceMode, :value => "isolated" }
354
+ ]
355
+ end
356
+
357
+ def ip_collection
358
+ @ip_collection ||= MockNetworkIps.new({}, self)
359
+ end
360
+
361
+ def extensions
362
+ @extensions ||= MockNetworkExtensions.new({}, self)
363
+ end
364
+
365
+ def random_ip
366
+ usable_subnet_ips[rand(usable_subnet_ips.length)]
367
+ end
368
+
369
+ # for TM eCloud. should probably be a subclass
370
+ def rnat
371
+ self[:rnat]
372
+ end
373
+
374
+ def usable_subnet_ips
375
+ subnet_ips[3..-2]
376
+ end
377
+
378
+ def address
379
+ subnet_ips.first
380
+ end
381
+
382
+ def broadcast
383
+ subnet_ips.last
384
+ end
385
+
386
+ private
387
+
388
+ def subnet_ipaddr
389
+ @ipaddr ||= IPAddr.new(subnet)
390
+ end
391
+
392
+ def subnet_ips
393
+ subnet_ipaddr.to_range.to_a.map(&:to_s)
394
+ end
395
+ end
396
+
397
+ class MockNetworkIps < Base
398
+ def items
399
+ @items ||= _parent.usable_subnet_ips.inject({}) do |out, subnet_ip|
400
+ out.update(subnet_ip => MockNetworkIp.new({ :ip => subnet_ip }, self))
401
+ end
402
+ end
403
+
404
+ def ordered_ips
405
+ items.values.sort_by {|i| i.ip.split(".").map(&:to_i) }
406
+ end
407
+
408
+ def name
409
+ "IP Addresses"
410
+ end
411
+ end
412
+
413
+ class MockNetworkIp < Base
414
+ def name
415
+ self[:name] || ip
416
+ end
417
+
418
+ def ip
419
+ self[:ip]
420
+ end
421
+
422
+ def used_by
423
+ self[:used_by] || _parent._parent._parent.virtual_machines.detect {|v| v.ip == ip }
424
+ end
425
+
426
+ def status
427
+ if used_by
428
+ "Assigned"
429
+ else
430
+ "Available"
431
+ end
432
+ end
433
+
434
+ def rnat
435
+ self[:rnat] || _parent._parent.rnat
436
+ end
437
+ end
438
+
439
+ class MockNetworkExtensions < Base
440
+ def name
441
+ _parent.name
442
+ end
443
+
444
+ def gateway
445
+ _parent.gateway
446
+ end
447
+
448
+ def broadcast
449
+ _parent.broadcast
450
+ end
451
+
452
+ def address
453
+ _parent.address
454
+ end
455
+
456
+ def rnat
457
+ _parent.rnat
458
+ end
459
+ end
460
+
461
+ class MockVirtualMachine < Base
462
+ def name
463
+ self[:name]
464
+ end
465
+
466
+ def ip
467
+ self[:ip]
468
+ end
469
+
470
+ def cpus
471
+ self[:cpus] || 1
472
+ end
473
+
474
+ def memory
475
+ self[:memory] || 1024
476
+ end
477
+
478
+ def disks
479
+ @disks ||= MockVirtualMachineDisks.new(self)
480
+ end
481
+
482
+ def status
483
+ self[:status] || 2
484
+ end
485
+
486
+ def power_off!
487
+ self[:status] = 2
488
+ end
489
+
490
+ def power_on!
491
+ self[:status] = 4
492
+ end
493
+
494
+ def size
495
+ disks.inject(0) {|s, d| s + d.vcloud_size }
496
+ end
497
+
498
+ # from fog ecloud server's _compose_vapp_data
499
+ def to_configure_vapp_hash
500
+ {
501
+ :name => name,
502
+ :cpus => cpus,
503
+ :memory => memory,
504
+ :disks => disks.map {|d| { :number => d.address.to_s, :size => d.vcloud_size, :resource => d.vcloud_size.to_s } }
505
+ }
506
+ end
507
+
508
+ def href(purpose = :base)
509
+ case purpose
510
+ when :base
511
+ super()
512
+ when :power_on
513
+ super() + "/power/action/powerOn"
514
+ when :power_off
515
+ super() + "/power/action/powerOff"
516
+ end
517
+ end
518
+ end
519
+
520
+ class MockVirtualMachineDisks < Array
521
+ def initialize(parent = nil)
522
+ @parent = parent
523
+ end
524
+
525
+ def _parent
526
+ @parent
527
+ end
528
+
529
+ def <<(disk)
530
+ next_address = 0
531
+ disk_with_max_address = max {|a, b| a[:address] <=> b[:address] }
532
+ disk_with_max_address && next_address = disk_with_max_address.address + 1
533
+ disk[:address] ||= next_address
534
+
535
+ super(disk)
536
+
537
+ if (addresses = map {|d| d.address }).uniq.size != size
538
+ raise "Duplicate disk address in: #{addresses.inspect} (#{size})"
539
+ end
540
+
541
+ sort! {|a, b| a.address <=> b.address }
542
+ self
543
+ end
544
+
545
+ def at_address(address)
546
+ detect {|d| d.address == address }
547
+ end
548
+ end
549
+
550
+ class MockVirtualMachineDisk < Base
551
+ def size
552
+ self[:size].to_i
553
+ end
554
+
555
+ def vcloud_size
556
+ # kilobytes
557
+ size * 1024
558
+ end
559
+
560
+ def address
561
+ self[:address].to_i
562
+ end
563
+ end
564
+
565
+ # for Terremark eCloud
566
+
567
+ class MockVdcInternetServices < Base
568
+ def href
569
+ _parent.href + "/internetServices"
570
+ end
571
+
572
+ def name
573
+ "Internet Services"
574
+ end
575
+
576
+ def items
577
+ _parent.public_ip_collection.items.inject([]) do |services, public_ip|
578
+ services + public_ip.internet_service_collection.items
579
+ end
580
+ end
581
+ end
582
+
583
+ class MockFirewallAcls < Base
584
+ def name
585
+ "Firewall Access List"
586
+ end
587
+ end
588
+
589
+ class MockPublicIps < Base
590
+ def name
591
+ self[:name] || "Public IPs"
592
+ end
593
+
594
+ def items
595
+ @items ||= []
596
+ end
597
+ end
598
+
599
+ class MockPublicIp < Base
600
+ def name
601
+ self[:name]
602
+ end
603
+
604
+ def internet_service_collection
605
+ @internet_service_collection ||= MockPublicIpInternetServices.new({}, self)
606
+ end
607
+ end
608
+
609
+ class MockPublicIpInternetServices < Base
610
+ def href
611
+ _parent.href + "/internetServices"
612
+ end
613
+
614
+ def items
615
+ @items ||= []
616
+ end
617
+ end
618
+
619
+ class MockPublicIpInternetService < Base
620
+ def name
621
+ self[:name] || "Public IP Service #{object_id}"
622
+ end
623
+
624
+ def description
625
+ self[:description] || "Description for Public IP Service #{name}"
626
+ end
627
+
628
+ def protocol
629
+ self[:protocol]
630
+ end
631
+
632
+ def port
633
+ self[:port]
634
+ end
635
+
636
+ def enabled
637
+ !!self[:enabled]
638
+ end
639
+
640
+ def redirect_url
641
+ self[:redirect_url]
642
+ end
643
+
644
+ def timeout
645
+ self[:timeout] || 2
646
+ end
647
+
648
+ def node_collection
649
+ @node_collection ||= MockPublicIpInternetServiceNodes.new({}, self)
650
+ end
651
+
652
+ def monitor
653
+ nil
654
+ end
655
+ end
656
+
657
+ class MockPublicIpInternetServiceNodes < Base
658
+ def href
659
+ _parent.href + "/nodeServices"
660
+ end
661
+
662
+ def items
663
+ @items ||= [].tap do |node_array|
664
+ node_array.instance_variable_set("@default_port", _parent.port)
665
+
666
+ def node_array.<<(node)
667
+ node[:port] ||= @default_port
668
+ super
669
+ end
670
+ end
671
+ end
672
+ end
673
+
674
+ class MockPublicIpInternetServiceNode < Base
675
+ def ip_address
676
+ self[:ip_address]
677
+ end
678
+
679
+ def name
680
+ self[:name] || "Public IP Service Node #{object_id}"
681
+ end
682
+
683
+ def description
684
+ self[:description] || "Description for Public IP Service Node #{name}"
685
+ end
686
+
687
+ def port
688
+ self[:port]
689
+ end
690
+
691
+ def enabled
692
+ self[:enabled].to_s.downcase != "false"
693
+ end
694
+
695
+ def enabled=(new_value)
696
+ self[:enabled] = new_value
697
+ end
698
+ end
699
+ end
700
+ end
701
+ end