fog 0.3.16 → 0.3.17

Sign up to get free protection for your applications and to get access to all the features.
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