ruby_vcloud_sdk 0.4.8 → 0.5.1

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 (145) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +296 -0
  3. data/lib/ruby_vcloud_sdk.rb +0 -4
  4. data/lib/ruby_vcloud_sdk/catalog.rb +377 -0
  5. data/lib/ruby_vcloud_sdk/catalog_item.rb +26 -0
  6. data/lib/ruby_vcloud_sdk/client.rb +25 -882
  7. data/lib/ruby_vcloud_sdk/config.rb +1 -7
  8. data/lib/ruby_vcloud_sdk/connection/connection.rb +114 -54
  9. data/lib/ruby_vcloud_sdk/cpu.rb +11 -0
  10. data/lib/ruby_vcloud_sdk/disk.rb +55 -0
  11. data/lib/ruby_vcloud_sdk/edge_gateway.rb +32 -0
  12. data/lib/ruby_vcloud_sdk/infrastructure.rb +135 -0
  13. data/lib/ruby_vcloud_sdk/ip_ranges.rb +95 -0
  14. data/lib/ruby_vcloud_sdk/memory.rb +11 -0
  15. data/lib/ruby_vcloud_sdk/network.rb +32 -0
  16. data/lib/ruby_vcloud_sdk/powerable.rb +78 -0
  17. data/lib/ruby_vcloud_sdk/resources.rb +13 -0
  18. data/lib/ruby_vcloud_sdk/session.rb +46 -0
  19. data/lib/ruby_vcloud_sdk/vapp.rb +122 -0
  20. data/lib/ruby_vcloud_sdk/vdc.rb +210 -0
  21. data/lib/ruby_vcloud_sdk/vdc_storage_profile.rb +23 -0
  22. data/lib/ruby_vcloud_sdk/version.rb +1 -1
  23. data/lib/ruby_vcloud_sdk/vm.rb +132 -0
  24. data/lib/ruby_vcloud_sdk/xml/constants.rb +6 -4
  25. data/lib/ruby_vcloud_sdk/xml/wrapper.rb +109 -30
  26. data/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb +45 -2
  27. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/admin_catalog.rb +13 -4
  28. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/allocated_ip_addresses.rb +9 -0
  29. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb +6 -14
  30. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk.rb +24 -14
  31. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk_attach_or_detach_params.rb +0 -2
  32. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk_create_params.rb +1 -3
  33. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway.rb +13 -0
  34. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/gateway_interface.rb +22 -0
  35. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb +4 -4
  36. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_address.rb +10 -0
  37. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_range.rb +13 -0
  38. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_ranges.rb +9 -0
  39. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_scope.rb +6 -32
  40. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/item.rb +1 -7
  41. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/link.rb +14 -0
  42. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/media.rb +4 -20
  43. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/media_insert_or_eject_params.rb +1 -3
  44. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network_connection_section.rb +0 -4
  45. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/nic_item_wrapper.rb +0 -2
  46. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/org.rb +44 -0
  47. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb +11 -3
  48. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/query_result_records.rb +14 -0
  49. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/recompose_vapp_params.rb +42 -0
  50. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/session.rb +5 -5
  51. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/supported_versions.rb +19 -0
  52. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/task.rb +1 -1
  53. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/upload_vapp_template_params.rb +2 -4
  54. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb +13 -22
  55. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb +0 -2
  56. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vcloud.rb +5 -3
  57. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb +72 -15
  58. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/virtual_hardware_section.rb +8 -6
  59. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb +29 -25
  60. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vms.rb +12 -0
  61. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminCatalog.xml +6 -1
  62. data/lib/ruby_vcloud_sdk/xml/xml_templates/RecomposeVAppParams.xml +16 -1
  63. metadata +116 -233
  64. data/README +0 -1
  65. data/Rakefile +0 -50
  66. data/lib/ruby_vcloud_sdk/util.rb +0 -21
  67. data/spec/assets/admin_org_response.xml +0 -75
  68. data/spec/assets/catalog_add_item_response.xml +0 -8
  69. data/spec/assets/catalog_add_vapp_request.xml +0 -5
  70. data/spec/assets/catalog_item_added_response.xml +0 -19
  71. data/spec/assets/catalog_response.xml +0 -19
  72. data/spec/assets/existing_media_busy_response.xml +0 -19
  73. data/spec/assets/existing_media_catalog_item.xml +0 -8
  74. data/spec/assets/existing_media_delete_task_done.xml +0 -6
  75. data/spec/assets/existing_media_done_response.xml +0 -11
  76. data/spec/assets/existing_vapp_resolver_response.xml +0 -3
  77. data/spec/assets/existing_vapp_template_catalog_resolver_response.xml +0 -3
  78. data/spec/assets/existing_vapp_template_instantiate_response.xml +0 -20
  79. data/spec/assets/existing_vapp_template_instantiate_task_error_response.xml +0 -7
  80. data/spec/assets/existing_vapp_template_instantiate_task_start_response.xml +0 -7
  81. data/spec/assets/existing_vapp_template_instantiate_task_success_response.xml +0 -7
  82. data/spec/assets/existing_vapp_template_item_response.xml +0 -8
  83. data/spec/assets/existing_vapp_template_ready_response.xml +0 -79
  84. data/spec/assets/finalize_upload_task_done_response.xml +0 -7
  85. data/spec/assets/finalize_upload_task_response.xml +0 -7
  86. data/spec/assets/indy_disk_attach_request.xml +0 -3
  87. data/spec/assets/indy_disk_attach_task.xml +0 -6
  88. data/spec/assets/indy_disk_attach_task_error.xml +0 -6
  89. data/spec/assets/indy_disk_create_error.xml +0 -1
  90. data/spec/assets/indy_disk_create_request.xml +0 -4
  91. data/spec/assets/indy_disk_create_response.xml +0 -19
  92. data/spec/assets/indy_disk_delete_task.xml +0 -6
  93. data/spec/assets/indy_disk_detach_request.xml +0 -3
  94. data/spec/assets/indy_disk_detach_task.xml +0 -6
  95. data/spec/assets/indy_disk_response.xml +0 -11
  96. data/spec/assets/instantiated_suspended_vapp_response.xml +0 -209
  97. data/spec/assets/instantiated_vapp_delelete_done_task.xml +0 -5
  98. data/spec/assets/instantiated_vapp_delelete_running_task.xml +0 -6
  99. data/spec/assets/instantiated_vapp_network_config_add_network_request.xml +0 -36
  100. data/spec/assets/instantiated_vapp_network_config_modify_network_task_success.xml +0 -6
  101. data/spec/assets/instantiated_vapp_network_config_remove_network_request.xml +0 -6
  102. data/spec/assets/instantiated_vapp_network_config_section_response.xml +0 -17
  103. data/spec/assets/instantiated_vapp_off_response.xml +0 -206
  104. data/spec/assets/instantiated_vapp_on_response.xml +0 -205
  105. data/spec/assets/instantiated_vapp_power_task_running.xml +0 -6
  106. data/spec/assets/instantiated_vapp_power_task_success.xml +0 -6
  107. data/spec/assets/instantiated_vapp_response.xml +0 -205
  108. data/spec/assets/instantiated_vm_change_task_running.xml +0 -6
  109. data/spec/assets/instantiated_vm_change_task_success.xml +0 -6
  110. data/spec/assets/instantiated_vm_cpu_response.xml +0 -11
  111. data/spec/assets/instantiated_vm_insert_media_task_done.xml +0 -6
  112. data/spec/assets/instantiated_vm_memory_response.xml +0 -11
  113. data/spec/assets/instantiated_vm_modify_task_running.xml +0 -6
  114. data/spec/assets/instantiated_vm_modify_task_success.xml +0 -5
  115. data/spec/assets/instantiated_vm_network_section_response.xml +0 -11
  116. data/spec/assets/instantiated_vm_response.xml +0 -149
  117. data/spec/assets/media_add_to_catalog_request.xml +0 -5
  118. data/spec/assets/media_add_to_catalog_response.xml +0 -8
  119. data/spec/assets/media_delete_task_done.xml +0 -6
  120. data/spec/assets/media_upload_pending_response.xml +0 -13
  121. data/spec/assets/media_upload_request.xml +0 -2
  122. data/spec/assets/metadata_set_request.xml +0 -3
  123. data/spec/assets/metadata_set_task_done.xml +0 -6
  124. data/spec/assets/org_network_response.xml +0 -22
  125. data/spec/assets/reconfigure_vm_request.xml +0 -133
  126. data/spec/assets/reconfigure_vm_task.xml +0 -8
  127. data/spec/assets/session.xml +0 -7
  128. data/spec/assets/test-config.yml +0 -38
  129. data/spec/assets/undeploy_params.xml +0 -1
  130. data/spec/assets/vapp_template_catalog_resolver_response.xml +0 -3
  131. data/spec/assets/vapp_template_delelete_done_task.xml +0 -5
  132. data/spec/assets/vapp_template_delelete_running_task.xml +0 -6
  133. data/spec/assets/vapp_template_instantiate_request.xml +0 -8
  134. data/spec/assets/vapp_template_instantiate_with_locality_request.xml +0 -14
  135. data/spec/assets/vapp_template_no_disk_response.xml +0 -27
  136. data/spec/assets/vapp_template_ready_response.xml +0 -79
  137. data/spec/assets/vapp_template_upload_complete.xml +0 -28
  138. data/spec/assets/vapp_template_upload_failed.xml +0 -28
  139. data/spec/assets/vapp_template_upload_request.xml +0 -4
  140. data/spec/assets/vapp_template_upload_response.xml +0 -25
  141. data/spec/assets/vcloud_response.xml +0 -56
  142. data/spec/assets/vdc_response.xml +0 -57
  143. data/spec/spec_helper.rb +0 -107
  144. data/spec/unit/client_response.rb +0 -700
  145. data/spec/unit/client_spec.rb +0 -1152
@@ -0,0 +1,95 @@
1
+ require "netaddr"
2
+ require "set"
3
+
4
+ module VCloudSdk
5
+ class IpRanges
6
+ attr_reader :ranges
7
+
8
+ def initialize(value = nil)
9
+ @ranges = Set.new
10
+
11
+ parse_ip_ranges(value) unless value.nil?
12
+ end
13
+
14
+ def add(ip_ranges)
15
+ ip_ranges = objectify ip_ranges
16
+ result = IpRanges.new
17
+ result.ranges.merge @ranges
18
+ result.ranges.merge ip_ranges.ranges
19
+ result
20
+ end
21
+ alias_method :+, :add
22
+
23
+ def subtract(ip_ranges)
24
+ ip_ranges = objectify ip_ranges
25
+ difference = IpRanges.new
26
+ difference.ranges.merge @ranges
27
+ difference.ranges.subtract ip_ranges.ranges
28
+
29
+ difference
30
+ end
31
+ alias_method :-, :subtract
32
+
33
+ def include?(ip_ranges)
34
+ ip_ranges = objectify ip_ranges
35
+ @ranges.superset? ip_ranges.ranges
36
+ end
37
+
38
+ protected
39
+
40
+ attr_writer :ranges
41
+
42
+ private
43
+
44
+ def parse_ip_ranges(ip_ranges_string)
45
+ fail "Parameter is not a string" unless ip_ranges_string.is_a? String
46
+
47
+ # remove white space
48
+ ip_ranges_string.gsub(/\s+/, "").split(",").map do |i|
49
+ parse_ip_range(i)
50
+ end
51
+ end
52
+
53
+ def parse_ip_range(ip_range_string)
54
+ case ip_range_string
55
+ when /-/
56
+ ips = ip_range_string.split("-")
57
+ unless ips.length == 2
58
+ fail "Invalid input: #{ips.length} field/fields separated by '-'"
59
+ end
60
+
61
+ ips ips[0], ips[1]
62
+ when /\//
63
+ ips = NetAddr::CIDR.create(ip_range_string)
64
+ ips ips.first, ips.last
65
+ else
66
+ # A single IP address such as "10.142.15.11"
67
+ ip = NetAddr::CIDR.create(ip_range_string)
68
+ fail "IPv6 is not supported" if ip.is_a?(NetAddr::CIDRv6)
69
+ @ranges.add ip.ip
70
+ end
71
+ end
72
+
73
+ def ips(ip_start_string, ip_end_string)
74
+ ip_start = NetAddr::CIDR.create(ip_start_string)
75
+ ip_end = NetAddr::CIDR.create(ip_end_string)
76
+ if ip_start.is_a?(NetAddr::CIDRv6) || ip_end.is_a?(NetAddr::CIDRv6)
77
+ fail "IPv6 is not supported"
78
+ end
79
+
80
+ if ip_start > ip_end
81
+ fail "IP #{ip_start.ip} is bigger than IP #{ip_end.ip}"
82
+ end
83
+
84
+ @ranges.merge((ip_start..ip_end).map(&:ip))
85
+ end
86
+
87
+ def objectify(ip_ranges)
88
+ ip_ranges = IpRanges.new(ip_ranges) if ip_ranges.is_a? String
89
+ unless ip_ranges.is_a? IpRanges
90
+ fail "Unable to parse object that is not IpRange or string"
91
+ end
92
+ ip_ranges
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,11 @@
1
+ module VCloudSdk
2
+
3
+ class Memory
4
+ attr_reader :available_mb
5
+
6
+ def initialize(available_mb)
7
+ @available_mb = available_mb
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,32 @@
1
+ require_relative "infrastructure"
2
+ require_relative "ip_ranges"
3
+
4
+ module VCloudSdk
5
+ class Network
6
+ include Infrastructure
7
+
8
+ def initialize(session, link)
9
+ @session = session
10
+ @link = link
11
+ end
12
+
13
+ def name
14
+ entity_xml.name
15
+ end
16
+
17
+ def ip_ranges
18
+ entity_xml.ip_ranges
19
+ .ranges
20
+ .reduce(IpRanges.new) do |result, i|
21
+ result + IpRanges.new("#{i.start_address}-#{i.end_address}")
22
+ end
23
+ end
24
+
25
+ def allocated_ips
26
+ allocated_addresses = connection.get(entity_xml.allocated_addresses_link)
27
+ allocated_addresses.ip_addresses.map do |i|
28
+ i.ip_address
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,78 @@
1
+ module VCloudSdk
2
+ # Shared functions by classes VM and VApp
3
+ module Powerable
4
+ def status
5
+ status_code = entity_xml[:status].to_i
6
+ Xml::RESOURCE_ENTITY_STATUS.each_pair do |k, v|
7
+ return k.to_s if v == status_code
8
+ end
9
+
10
+ fail CloudError,
11
+ "Fail to find corresponding status for code '#{status_code}'"
12
+ end
13
+
14
+ # Power on VApp or VM
15
+ def power_on
16
+ target = entity_xml
17
+ class_name = self.class.name.split("::").last
18
+ Config.logger.debug "#{class_name} status: #{target[:status]}"
19
+ if is_status?(target, :POWERED_ON)
20
+ Config.logger.info "#{class_name} #{target.name} is already powered-on."
21
+ return
22
+ end
23
+
24
+ power_on_link = target.power_on_link
25
+ unless power_on_link
26
+ fail CloudError,
27
+ "#{class_name} #{target.name} not in a state able to power on."
28
+ end
29
+
30
+ Config.logger.info "Powering on #{class_name} #{target.name}."
31
+ task = connection.post(power_on_link, nil)
32
+ task = monitor_task task, @session.time_limit[:power_on]
33
+ Config.logger.info "#{class_name} #{target.name} is powered on."
34
+ task
35
+ end
36
+
37
+ # Power off VApp or VM
38
+ def power_off
39
+ target = entity_xml
40
+ class_name = self.class.name.split("::").last
41
+ Config.logger.debug "#{class_name} status: #{target[:status]}"
42
+ if is_status?(target, :SUSPENDED)
43
+ error_msg = "#{class_name} #{target.name} suspended, discard state before powering off."
44
+ fail class_name == "VApp" ? VappSuspendedError : VmSuspendedError,
45
+ error_msg
46
+ end
47
+ if is_status?(target, :POWERED_OFF)
48
+ Config.logger.info "#{class_name} #{target.name} is already powered off."
49
+ return
50
+ end
51
+
52
+ power_off_link = target.power_off_link
53
+ unless power_off_link
54
+ fail CloudError, "#{class_name} #{target.name} is not in a state that could be powered off."
55
+ end
56
+
57
+ task = connection.post(power_off_link, nil)
58
+ monitor_task task, @session.time_limit[:power_off]
59
+ Config.logger.info "#{class_name} #{target.name} is powered off."
60
+
61
+ undeploy(target, class_name)
62
+ end
63
+
64
+ private
65
+
66
+ def is_status?(target, status)
67
+ target[:status] == Xml::RESOURCE_ENTITY_STATUS[status].to_s
68
+ end
69
+
70
+ def undeploy(target, class_name)
71
+ params = Xml::WrapperFactory.create_instance("UndeployVAppParams") # Even for VM it's called UndeployVappParams
72
+ task = connection.post(target.undeploy_link, params)
73
+ task = monitor_task(task, @session.time_limit[:undeploy])
74
+ Config.logger.info "#{class_name} #{target.name} is undeployed."
75
+ task
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,13 @@
1
+ module VCloudSdk
2
+
3
+ class Resources
4
+ attr_reader :cpu
5
+ attr_reader :memory
6
+
7
+ def initialize(cpu, memory)
8
+ @cpu = cpu
9
+ @memory = memory
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ module VCloudSdk
2
+ class Session
3
+ attr_reader :connection
4
+ attr_accessor :retries, :time_limit, :delay
5
+
6
+ RETRIES = {
7
+ default: 5,
8
+ upload_vapp_files: 7,
9
+ cpi: 1,
10
+ }
11
+
12
+ TIME_LIMIT_SEC = {
13
+ default: 120,
14
+ delete_vapp_template: 120,
15
+ delete_vapp: 120,
16
+ delete_media: 120,
17
+ instantiate_vapp_template: 300,
18
+ power_on: 600,
19
+ power_off: 600,
20
+ undeploy: 720,
21
+ process_descriptor_vapp_template: 300,
22
+ http_request: 240,
23
+ recompose_vapp: 200,
24
+ }
25
+
26
+ DELAY = 1
27
+
28
+ private_constant :RETRIES, :TIME_LIMIT_SEC, :DELAY
29
+
30
+ def initialize(url, username, password, options)
31
+ @time_limit = options[:time_limit_sec] || TIME_LIMIT_SEC
32
+ @retries = options[:retries] || RETRIES
33
+ @delay = options[:delay] || DELAY
34
+ @connection = Connection::Connection.new(
35
+ url,
36
+ @time_limit[:http_request])
37
+ @session_xml_obj = @connection.connect(username, password)
38
+ @org_link = @session_xml_obj.organization
39
+ end
40
+
41
+ def org
42
+ @connection.get(@org_link)
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,122 @@
1
+ require_relative "infrastructure"
2
+ require_relative "powerable"
3
+ require_relative "vm"
4
+
5
+ module VCloudSdk
6
+ class VApp
7
+ include Infrastructure
8
+ include Powerable
9
+
10
+ def initialize(session, link)
11
+ @session = session
12
+ @link = link
13
+ end
14
+
15
+ def name
16
+ entity_xml.name
17
+ end
18
+
19
+ def delete
20
+ vapp = entity_xml
21
+ vapp_name = name
22
+
23
+ if is_status?(vapp, :POWERED_ON)
24
+ fail CloudError,
25
+ "vApp #{vapp_name} is powered on, power-off before deleting."
26
+ end
27
+
28
+ wait_for_running_tasks(vapp, "VApp #{vapp_name}")
29
+
30
+ Config.logger.info "Deleting vApp #{vapp_name}."
31
+ monitor_task(connection.delete(vapp.remove_link),
32
+ @session.time_limit[:delete_vapp]) do |task|
33
+ Config.logger.info "vApp #{vapp_name} deleted."
34
+ return task
35
+ end
36
+
37
+ fail ApiRequestError,
38
+ "Fail to delete vApp #{vapp_name}"
39
+ end
40
+
41
+ def recompose_from_vapp_template(catalog_name, template_name)
42
+ recompose_vapp_link = get_recompose_vapp_link
43
+
44
+ Config.logger.info "Recomposing from template '#{template_name}' in catalog '#{catalog_name}'."
45
+ catalog = find_catalog_by_name catalog_name
46
+
47
+ template = catalog.find_vapp_template_by_name template_name
48
+
49
+ task = connection.post recompose_vapp_link.href,
50
+ recompose_from_vapp_template_param(template)
51
+
52
+ monitor_task task, @session.time_limit[:recompose_vapp]
53
+ Config.logger.info "vApp #{name} is recomposed."
54
+ self
55
+ end
56
+
57
+ def vms
58
+ entity_xml.vms.map do |vm|
59
+ VCloudSdk::VM.new(@session, vm.href)
60
+ end
61
+ end
62
+
63
+ def list_vms
64
+ entity_xml.vms.map do |vm|
65
+ vm.name
66
+ end
67
+ end
68
+
69
+ def find_vm_by_name(name)
70
+ entity_xml.vms.each do |vm|
71
+ return VCloudSdk::VM.new(@session, vm.href) if vm.name == name
72
+ end
73
+
74
+ fail ObjectNotFoundError, "VM '#{name}' is not found"
75
+ end
76
+
77
+ def remove_vm_by_name(vm_name)
78
+ target_vm = find_vm_by_name vm_name
79
+ recompose_vapp_link = get_recompose_vapp_link
80
+
81
+ task = connection.post recompose_vapp_link.href,
82
+ remove_vm_param(target_vm)
83
+
84
+ monitor_task task, @session.time_limit[:recompose_vapp]
85
+ Config.logger.info "VM #{vm_name} is removed."
86
+ self
87
+ end
88
+
89
+ private
90
+
91
+ def recompose_from_vapp_template_param(template)
92
+ Xml::WrapperFactory.create_instance("RecomposeVAppParams").tap do |params|
93
+ params.name = name
94
+ params.all_eulas_accepted = true
95
+ params.add_source_item template.href
96
+ end
97
+ end
98
+
99
+ def get_recompose_vapp_link
100
+ recompose_vapp_link = connection
101
+ .get(@link)
102
+ .recompose_vapp_link
103
+
104
+ if recompose_vapp_link.nil?
105
+ # We are able to recompose vapp when it is suspended or powered off
106
+ # If vapp is powered on, throw exception
107
+ fail CloudError,
108
+ "VApp is in status of '#{status}' and can not be recomposed"
109
+ end
110
+
111
+ recompose_vapp_link
112
+ end
113
+
114
+ def remove_vm_param(vm)
115
+ Xml::WrapperFactory.create_instance("RecomposeVAppParams").tap do |params|
116
+ params.name = name
117
+ params.all_eulas_accepted = true
118
+ params.add_delete_item vm.href
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,210 @@
1
+ require "forwardable"
2
+ require "uri"
3
+ require_relative "vdc_storage_profile"
4
+ require_relative "vapp"
5
+ require_relative "infrastructure"
6
+ require_relative "resources"
7
+ require_relative "cpu"
8
+ require_relative "disk"
9
+ require_relative "memory"
10
+ require_relative "network"
11
+ require_relative "edge_gateway"
12
+
13
+ module VCloudSdk
14
+ class VDC
15
+ include Infrastructure
16
+
17
+ extend Forwardable
18
+ def_delegators :@vdc_xml_obj,
19
+ :name, :upload_link, :upload_media_link,
20
+ :instantiate_vapp_template_link
21
+
22
+ BUS_TYPE = {
23
+ "scsi" => Xml::HARDWARE_TYPE[:SCSI_CONTROLLER]
24
+ }
25
+
26
+ BUS_SUB_TYPE = {
27
+ "lsilogic" => Xml::BUS_SUB_TYPE[:LSILOGIC]
28
+ }
29
+
30
+ private_constant :BUS_TYPE, :BUS_SUB_TYPE
31
+
32
+ def initialize(session, vdc_xml_obj)
33
+ @session = session
34
+ @vdc_xml_obj = vdc_xml_obj
35
+ end
36
+
37
+ def storage_profiles
38
+ storage_profile_records.map do |storage_profile|
39
+ VCloudSdk::VdcStorageProfile.new(storage_profile)
40
+ end
41
+ end
42
+
43
+ def list_storage_profiles
44
+ storage_profile_records.map do |storage_profile|
45
+ storage_profile.name
46
+ end
47
+ end
48
+
49
+ def find_storage_profile_by_name(name)
50
+ storage_profile_records.each do |storage_profile|
51
+ if storage_profile.name == name
52
+ return VCloudSdk::VdcStorageProfile.new(storage_profile)
53
+ end
54
+ end
55
+
56
+ fail ObjectNotFoundError, "Storage profile '#{name}' is not found"
57
+ end
58
+
59
+ def vapps
60
+ @vdc_xml_obj.vapps.map do |vapp_link|
61
+ VCloudSdk::VApp.new(@session, vapp_link)
62
+ end
63
+ end
64
+
65
+ def list_vapps
66
+ @vdc_xml_obj.vapps.map do |vapp_link|
67
+ vapp_link.name
68
+ end
69
+ end
70
+
71
+ def find_vapp_by_name(name)
72
+ @vdc_xml_obj.vapps.each do |vapp_link|
73
+ if vapp_link.name == name
74
+ return VCloudSdk::VApp.new(@session, vapp_link)
75
+ end
76
+ end
77
+
78
+ fail ObjectNotFoundError, "VApp '#{name}' is not found"
79
+ end
80
+
81
+ def resources
82
+ cpu = VCloudSdk::CPU.new(@vdc_xml_obj.available_cpu_cores)
83
+ memory = VCloudSdk::Memory.new(@vdc_xml_obj.available_memory_mb)
84
+ VCloudSdk::Resources.new(cpu, memory)
85
+ end
86
+
87
+ def networks
88
+ @session.org.networks.map do |network_link|
89
+ VCloudSdk::Network.new(@session, network_link)
90
+ end
91
+ end
92
+
93
+ def list_networks
94
+ @session.org.networks.map do |network_link|
95
+ network_link.name
96
+ end
97
+ end
98
+
99
+ def find_network_by_name(name)
100
+ @session.org.networks.each do |network_link|
101
+ if network_link.name == name
102
+ return VCloudSdk::Network.new(@session, network_link)
103
+ end
104
+ end
105
+
106
+ fail ObjectNotFoundError, "Network '#{name}' is not found"
107
+ end
108
+
109
+ def edge_gateways
110
+ connection
111
+ .get(@vdc_xml_obj.edge_gateways_link)
112
+ .edge_gateway_records
113
+ .map do |edge_gateway_link|
114
+ VCloudSdk::EdgeGateway.new(@session, edge_gateway_link.href)
115
+ end
116
+ end
117
+
118
+ def disks
119
+ @vdc_xml_obj.disks.map do |disk_link|
120
+ VCloudSdk::Disk.new(@session, disk_link)
121
+ end
122
+ end
123
+
124
+ def list_disks
125
+ @vdc_xml_obj.disks.map do |disk_link|
126
+ disk_link.name
127
+ end
128
+ end
129
+
130
+ def find_disks_by_name(name)
131
+ disks = @vdc_xml_obj
132
+ .disks
133
+ .select { |disk_link| disk_link.name == name }
134
+ .map { |disk_link| VCloudSdk::Disk.new(@session, disk_link.href) }
135
+
136
+ if disks.empty?
137
+ fail ObjectNotFoundError, "Disk '#{name}' is not found"
138
+ end
139
+
140
+ disks
141
+ end
142
+
143
+ def disk_exists?(name)
144
+ disks.any? do |disk|
145
+ disk.name == name
146
+ end
147
+ end
148
+
149
+ def create_disk(
150
+ name,
151
+ size_mb,
152
+ vm = nil,
153
+ bus_type = "scsi",
154
+ bus_sub_type = "lsilogic")
155
+
156
+ fail(CloudError,
157
+ "Invalid size in MB #{size_mb}") if size_mb <= 0
158
+
159
+ bus_type = BUS_TYPE[bus_type.downcase]
160
+ fail(CloudError,
161
+ "Invalid bus type!") unless bus_type
162
+
163
+ bus_sub_type = BUS_SUB_TYPE[bus_sub_type.downcase]
164
+ fail(CloudError,
165
+ "Invalid bus sub type!") unless bus_sub_type
166
+
167
+ Config
168
+ .logger
169
+ .info "Creating independent disk #{name} of #{size_mb}MB."
170
+
171
+ disk = connection.post(@vdc_xml_obj.add_disk_link,
172
+ disk_create_params(name, size_mb, bus_type, bus_sub_type, vm),
173
+ Xml::MEDIA_TYPE[:DISK_CREATE_PARAMS])
174
+
175
+ wait_for_running_tasks(disk, "Disk #{name}")
176
+
177
+ VCloudSdk::Disk.new(@session, disk.href)
178
+ end
179
+
180
+ def storage_profile_xml_node(name)
181
+ return nil if name.nil?
182
+
183
+ storage_profile = @vdc_xml_obj.storage_profile(name)
184
+ unless storage_profile
185
+ fail ObjectNotFoundError,
186
+ "Storage profile '#{name}' does not exist"
187
+ end
188
+
189
+ storage_profile
190
+ end
191
+
192
+ private
193
+
194
+ def storage_profile_records
195
+ connection
196
+ .get("/api/query?type=orgVdcStorageProfile&filter=vdcName==#{URI.encode(name)}")
197
+ .org_vdc_storage_profile_records
198
+ end
199
+
200
+ def disk_create_params(name, size_mb, bus_type, bus_sub_type, vm)
201
+ Xml::WrapperFactory.create_instance("DiskCreateParams").tap do |params|
202
+ params.name = name
203
+ params.size_bytes = size_mb * 1024 * 1024 # VCD expects bytes
204
+ params.bus_type = bus_type
205
+ params.bus_sub_type = bus_sub_type
206
+ params.add_locality(connection.get(vm.href)) if vm # Use xml form of vm
207
+ end
208
+ end
209
+ end
210
+ end