ruby_vcloud_sdk 0.4.8 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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,26 @@
1
+ require_relative "session"
2
+ require_relative "infrastructure"
3
+
4
+ module VCloudSdk
5
+ # Represents the calalog item in calalog.
6
+ class CatalogItem
7
+ include Infrastructure
8
+
9
+ def initialize(session, link)
10
+ @session = session
11
+ @link = link
12
+ end
13
+
14
+ def name
15
+ entity_xml.entity[:name]
16
+ end
17
+
18
+ def type
19
+ entity_xml.entity[:type]
20
+ end
21
+
22
+ def href
23
+ entity_xml.entity[:href]
24
+ end
25
+ end
26
+ end
@@ -1,899 +1,42 @@
1
- require "rest_client" # Need this for the exception classes
2
- require "set"
1
+ require_relative "vdc"
2
+ require_relative "catalog"
3
+ require_relative "session"
4
+ require_relative "infrastructure"
3
5
 
4
6
  module VCloudSdk
5
7
 
6
8
  class Client
7
- attr_reader :ovdc
9
+ include Infrastructure
8
10
 
9
- def initialize(url, username, password, entities, control,
10
- connection = nil)
11
- @logger = Config.logger
12
- @url = url
13
- @organization = entities["organization"]
14
- @ovdc_name = entities["virtual_datacenter"]
15
- @vapp_catalog_name = entities["vapp_catalog"]
16
- @media_catalog_name = entities["media_catalog"]
17
- @control = control
18
- @retries = @control["retries"]
19
- @time_limit = @control["time_limit_sec"]
20
- construct_rest_logger
21
- Config.configure({ "rest_logger" => @rest_logger,
22
- "rest_throttle" => control["rest_throttle"] })
23
-
24
- if connection
25
- @connection = connection
26
- else
27
- @connection = Connection::Connection.new(@url, @organization,
28
- @time_limit["http_request"])
29
- end
30
- @root = @connection.connect(username, password)
31
- @admin_root = @connection.get(@root.admin_root)
32
- @entity_resolver_link = @root.entity_resolver.href
33
- # We assume the organization does not change often so we can get it at
34
- # login and cache it
35
- @admin_org = @connection.get(@admin_root.organization(@organization))
36
- @logger.info("Successfully connected.")
37
- end
38
-
39
- def get_catalog_vapp(id)
40
- resolve_entity(id)
41
- end
42
-
43
- def get_vapp(obj)
44
- if obj.is_a?(Xml::VApp)
45
- obj
46
- elsif obj.is_a?(String)
47
- resolve_entity(obj)
48
- else
49
- raise CloudError, "Expecting Xml::VApp or String, got #{obj.inspect}."
50
- end
51
- end
52
-
53
- def upload_vapp_template(vapp_name, directory)
54
- ovdc = get_ovdc
55
- @logger.info("Uploading VM #{vapp_name} to #{ovdc["name"]} in " +
56
- "organization #{@organization}")
57
- # if directory behaves like an OVFDirectory, then use it
58
- is_ovf_directory = [:ovf_file, :ovf_file_path, :vmdk_file,
59
- :vmdk_file_path].reduce(true) do |present, name|
60
- present && directory.respond_to?(name)
61
- end
62
- ovf_directory = is_ovf_directory ? directory :
63
- OVFDirectory.new(directory)
64
- upload_params = Xml::WrapperFactory.create_instance(
65
- "UploadVAppTemplateParams")
66
- upload_params.name = vapp_name
67
- vapp_template = @connection.post(ovdc.upload_link, upload_params)
68
- catalog_name = @vapp_catalog_name
69
- vapp_template = upload_vapp_files(vapp_template, ovf_directory)
70
- raise ObjectNotFoundError, "Error uploading vApp template" unless
71
- vapp_template
72
- @logger.info("#{vapp_template.name} has tasks in progress. " +
73
- "Waiting until done.")
74
- vapp_template.running_tasks.each do |task|
75
- monitor_task(task, @time_limit["process_descriptor_vapp_template"])
76
- end
77
- err_tasks = @connection.get(vapp_template).tasks.find_all {
78
- |t| t.status != Xml::TASK_STATUS[:SUCCESS] }
79
- unless err_tasks.empty?
80
- @logger.error("Error uploading vApp template. " +
81
- "Non-successful tasks:#{err_tasks}.")
82
- raise CloudError, "Error uploading vApp template"
83
- end
84
- @logger.info("vApp #{vapp_name} uploaded, adding to " +
85
- "catalog #{catalog_name}")
86
- catalog_item = add_catalog_item(vapp_template, catalog_name)
87
- @logger.info("vApp #{vapp_name} added to catalog " +
88
- "#{catalog_name} #{catalog_item.to_s}")
89
- catalog_item
90
- rescue ApiError => e
91
- log_exception(e, "Error in uploading vApp template #{vapp_name}")
92
- rollback_upload_vapp(vapp_template)
93
- raise e
94
- end
95
-
96
- def insert_catalog_media(vm, catalog_media_name)
97
- catalog_media = get_catalog_media(catalog_media_name)
98
- media = @connection.get(catalog_media.entity)
99
- current_vm = @connection.get(vm)
100
- insert_media(current_vm, media)
101
- end
102
-
103
- def eject_catalog_media(vm, catalog_media_name)
104
- catalog_media = get_catalog_media(catalog_media_name)
105
- unless catalog_media
106
- raise CatalogMediaNotFoundError,
107
- "Catalog media #{catalog_media_name} not found."
108
- end
109
- media = @connection.get(catalog_media.entity)
110
- current_vm = @connection.get(vm)
111
- eject_media(current_vm, media)
112
- end
113
-
114
- def upload_catalog_media(media_name, file, storage_profile = nil,
115
- image_type = "iso")
116
- ovdc = get_ovdc
117
- @logger.info("Uploading media #{media_name} to #{storage_profile}/" +
118
- "#{ovdc["name"]} in organization #{@organization}")
119
- catalog_name = @media_catalog_name
120
- upload_params = Xml::WrapperFactory.create_instance("Media")
121
- upload_params.name = media_name
122
- media_file = file.is_a?(String) ? File.new(file, "rb") : file
123
- upload_params.size = media_file.stat.size
124
- upload_params.image_type = image_type
125
- upload_params.storage_profile = storage_profile
126
- media = @connection.post(ovdc.upload_media_link, upload_params)
127
- incomplete_file = media.incomplete_files.pop
128
- @connection.put_file(incomplete_file.upload_link, media_file)
129
- media = @connection.get(media)
130
- add_catalog_item(media, catalog_name)
131
- rescue ArgumentError, ApiError => e
132
- log_exception(e, "Error uploading media #{media_name}" +
133
- "to catalog #{catalog_name}. #{e.message}")
134
- delete_media(media) if media
135
- raise e
136
- end
137
-
138
- def delete_catalog_media(name)
139
- raise ArgumentError, "Media name cannot be nil." unless name
140
- catalog_media = get_catalog_media(name)
141
- if catalog_media
142
- media = @connection.get(catalog_media.entity)
143
- delete_media(media)
144
- @connection.delete(catalog_media)
145
- end
146
- rescue RestClient::ResourceNotFound => e
147
- # Media might be deleted already
148
- @logger.debug("Catalog media #{name} no longer exists.")
149
- end
150
-
151
- def delete_catalog_vapp(id)
152
- raise ArgumentError, "Catalog ID cannot be nil." unless id
153
- catalog_vapp = get_catalog_vapp(id)
154
- if catalog_vapp
155
- vapp = @connection.get(catalog_vapp.entity)
156
- delete_vapp_template(vapp)
157
- @connection.delete(catalog_vapp)
158
- end
159
- rescue => e
160
- # vApp template might be deleted already
161
- @logger.debug("Catalog vApp #{id} no longer exists.")
162
- end
163
-
164
- def delete_vapp(vapp)
165
- @logger.info("Deleting vApp #{vapp.name}.")
166
- current_vapp = @connection.get(vapp)
167
- if is_vapp_status(current_vapp, :POWERED_ON)
168
- raise CloudError,
169
- "vApp #{vapp.name} is powered on, power-off before deleting."
170
- end
171
- delete_vapp_or_template(current_vapp, @retries["default"],
172
- @time_limit["delete_vapp"], "vApp")
173
- end
174
-
175
- def instantiate_vapp_template(source_template_id, vapp_name,
176
- description = nil, disk_locality = nil)
177
- catalog_item = get_catalog_vapp(source_template_id)
178
- unless catalog_item
179
- @logger.error("Catalog item with ID #{source_template_id} not " +
180
- "found in catalog #{@vapp_catalog_name}.")
181
- raise ObjectNotFoundError, "Item with ID #{source_template_id} " +
182
- "not found in catalog #{@vapp_catalog_name}."
183
- end
184
- src_vapp_template = @connection.get(catalog_item.entity)
185
- instantiate_vapp_params = Xml::WrapperFactory.create_instance(
186
- "InstantiateVAppTemplateParams")
187
- instantiate_vapp_params.name = vapp_name
188
- instantiate_vapp_params.description = description
189
- instantiate_vapp_params.source = src_vapp_template
190
- instantiate_vapp_params.all_eulas_accepted = true
191
- instantiate_vapp_params.linked_clone = false
192
- instantiate_vapp_params.set_locality = locality_spec(src_vapp_template,
193
- disk_locality)
194
- vdc = get_ovdc
195
- vapp = @connection.post(vdc.instantiate_vapp_template_link,
196
- instantiate_vapp_params)
197
- vapp.running_tasks.each do |task|
198
- begin
199
- monitor_task(task, @time_limit["instantiate_vapp_template"])
200
- rescue ApiError => e
201
- log_exception(e, "Instantiate vApp template #{vapp_name} failed." +
202
- " Task #{task.operation} did not complete successfully.")
203
- delete_vapp(vapp)
204
- raise e
205
- end
206
- end
207
- @connection.get(vapp)
208
- end
209
-
210
- def reconfigure_vm(vm, &b)
211
- b.call(vm)
212
- monitor_task(@connection.post("#{vm.reconfigure_link.href}", vm,
213
- Xml::MEDIA_TYPE[:VM]))
214
- end
215
-
216
- def get_metadata(entity, key)
217
- metadata = @connection.get(generate_metadata_href(entity, key))
218
- metadata.value
219
- end
220
-
221
- def set_metadata(entity, key, value)
222
- metadata = Xml::WrapperFactory.create_instance("MetadataValue")
223
- metadata.value = value
224
- task = @connection.put(generate_metadata_href(entity, key), metadata,
225
- Xml::MEDIA_TYPE[:METADATA_ITEM_VALUE])
226
- monitor_task(task)
227
- end
228
-
229
- def delete_networks(vapp, exclude_nets = [])
230
- current_vapp = get_vapp(vapp)
231
- raise ObjectNotFoundError, "Cannot delete nets, vApp #{vapp.name} no " +
232
- "longer exists" unless current_vapp
233
- current = current_vapp.network_config_section.network_configs.map {
234
- |n| n.network_name }
235
- nets = current - exclude_nets
236
- @logger.debug("nets:: current:#{current}, exclude:#{exclude_nets}, " +
237
- "to delete:#{nets}")
238
- return if nets.nil? || nets.length == 0
239
- delete_network(current_vapp, *nets)
240
- end
241
-
242
- def add_network(vapp, network, vapp_net_name = nil,
243
- fence_mode = Xml::FENCE_MODES[:BRIDGED])
244
- current_network = @connection.get(network)
245
- raise ObjectNotFoundError, "Cannot add network to vApp #{vapp.name}. " +
246
- "The network #{network.name} no longer exists." unless current_network
247
- current_vapp = get_vapp(vapp)
248
- raise ObjectNotFoundError, "Cannot add network to vApp #{vapp.name}. " +
249
- "The vApp #{vapp.name} no longer exists." unless current_vapp
250
- network_config = Xml::WrapperFactory.create_instance("NetworkConfig")
251
- new_vapp_net_name = vapp_net_name.nil? ?
252
- current_network["name"] : vapp_net_name
253
- copy_network_settings(current_network, network_config,
254
- new_vapp_net_name, fence_mode)
255
- current_vapp.network_config_section.add_network_config(network_config)
256
- task = @connection.put(current_vapp.network_config_section,
257
- current_vapp.network_config_section,
258
- Xml::MEDIA_TYPE[:NETWORK_CONFIG_SECTION])
259
- monitor_task(task)
260
- end
261
-
262
- # There must be no NICs on the network when it is deleted. Otherwise the
263
- # task will fail. Use set_nic_network to move NICs onto other network or
264
- # the NONE network prior to deleting the network from the vApp.
265
- def delete_network(vapp, *network_names)
266
- raise ArgumentError, "Must specify a network name to delete." if
267
- network_names.nil? || network_names.length == 0
268
- unique_network_names = network_names.uniq
269
- @logger.info("Delete networks(s) #{unique_network_names.join(" ")} " +
270
- "from vApp #{vapp.name}")
271
- current_vapp = get_vapp(vapp)
272
- unique_network_names.each do |n|
273
- current_vapp.network_config_section.delete_network_config(n)
274
- end
275
- task = @connection.put(current_vapp.network_config_section,
276
- current_vapp.network_config_section,
277
- Xml::MEDIA_TYPE[:NETWORK_CONFIG_SECTION])
278
- monitor_task(task)
279
- end
280
-
281
- # Size at creation is in bytes
282
- # We currently assumes the disk is SCSI and bus sub type LSILOGIC
283
- def create_disk(name, size_mb, vm = nil, retries = @retries["default"])
284
- new_disk = Xml::WrapperFactory.create_instance("DiskCreateParams")
285
- new_disk.name = name
286
- new_disk.size_bytes = size_mb * 1024 * 1024 # VCD expects bytes
287
- new_disk.bus_type = Xml::HARDWARE_TYPE[:SCSI_CONTROLLER]
288
- new_disk.bus_sub_type = Xml::BUS_SUB_TYPE[:LSILOGIC]
289
- new_disk.add_locality(vm) if vm
290
- vdc = get_ovdc
291
- @logger.info("Creating independent disk #{name} of #{size_mb}MB.")
292
- @logger.info("Disk locality ist set to #{vm.name} #{vm.urn}.") if vm
293
- disk = @connection.post(vdc.add_disk_link, new_disk,
294
- Xml::MEDIA_TYPE[:DISK_CREATE_PARAMS])
295
- raise ApiRequestError unless disk.respond_to?(:running_tasks)
296
- # Creating a disk returns a disk with tasks inside
297
- retries.times do |try|
298
- return disk if disk.running_tasks.nil? || disk.running_tasks.empty?
299
- @logger.info("Disk #{disk.urn} has running tasks. Waiting for " +
300
- "tasks to finish. Try: #{try}/#{retries} ." )
301
- disk.running_tasks.each do |t|
302
- monitor_task(t)
303
- end
304
- disk = @connection.get(disk)
305
- end
306
- end
307
-
308
- def delete_disk(disk)
309
- current_disk = @connection.get(disk)
310
- unless current_disk
311
- @logger.warn("Disk #{disk.name} #{disk.urn} no longer exists.")
312
- return
313
- end
314
- task = @connection.delete(current_disk.delete_link)
315
- monitor_task(task) do |t|
316
- @logger.info("Deleted disk #{current_disk.name} #{current_disk.urn}")
317
- t
318
- end
319
- end
320
-
321
- def attach_disk(disk, vm)
322
- current_vm = @connection.get(vm)
323
- raise ObjectNotFoundError, "VM #{vm.name} not found." unless current_vm
324
-
325
- current_disk = @connection.get(disk)
326
- unless current_disk
327
- raise ObjectNotFoundError, "Disk #{disk.name} not found."
328
- end
329
-
330
- params = Xml::WrapperFactory.create_instance("DiskAttachOrDetachParams")
331
- params.disk_href = current_disk.href
332
- task = @connection.post(current_vm.attach_disk_link, params,
333
- Xml::MEDIA_TYPE[:DISK_ATTACH_DETACH_PARAMS])
334
- monitor_task(task) do |t|
335
- @logger.info("Attached disk #{current_disk.name} to VM " +
336
- "#{current_vm.name}.")
337
- t
338
- end
339
- end
340
-
341
- def detach_disk(disk, vm)
342
- current_vm = @connection.get(vm)
343
- raise ObjectNotFoundError, "VM #{vm.name} not found." unless current_vm
344
-
345
- current_disk = @connection.get(disk)
346
- unless current_disk
347
- raise ObjectNotFoundError, "Disk #{disk.name} not found."
348
- end
349
-
350
- disk_href = current_disk.href
351
-
352
- if is_vapp_status(current_vm, :SUSPENDED)
353
- @logger.debug("vApp #{current_vm.name} suspended, discard state " +
354
- "before detaching disk.")
355
- raise VmSuspendedError, "discard state first"
356
- end
357
-
358
- begin
359
- get_disk_id(current_vm, disk_href)
360
- rescue DiskNotFoundError
361
- @logger.warn("Disk #{current_disk.name} not found on VM " +
362
- "#{current_vm.name}. No need to detach.")
363
- return
364
- end
365
- params = Xml::WrapperFactory.create_instance("DiskAttachOrDetachParams")
366
- params.disk_href = disk_href
367
- task = @connection.post(current_vm.detach_disk_link, params,
368
- Xml::MEDIA_TYPE[:DISK_ATTACH_DETACH_PARAMS])
369
- monitor_task(task) do |t|
370
- @logger.info("Detached disk #{current_disk.name} from VM " +
371
- "#{current_vm.name}.")
372
- t
373
- end
374
- end
375
-
376
- def get_disk(disk_id)
377
- resolve_entity(disk_id)
378
- end
379
-
380
- def power_on_vapp(vapp)
381
- @logger.info("Powering on vApp #{vapp.name} .")
382
- current_vapp = @connection.get(vapp)
383
- unless current_vapp
384
- raise ObjectNotFoundError, "vApp #{vapp.name} not found."
385
- end
386
- @logger.debug("vApp status: #{current_vapp["status"]}")
387
- if is_vapp_status(current_vapp, :POWERED_ON)
388
- @logger.info("vApp #{vapp.name} already powered-on.")
389
- return
390
- end
391
- unless current_vapp.power_on_link
392
- raise CloudError, "vApp #{vapp.name} not in a state to be " +
393
- "powered on."
394
- end
395
- task = @connection.post(current_vapp.power_on_link, nil)
396
- monitor_task(task, @time_limit["power_on"])
397
- @logger.info("vApp #{current_vapp.name} powered on.")
398
- task
399
- end
400
-
401
- def power_off_vapp(vapp, undeploy = true)
402
- @logger.info("Powering off vApp #{vapp.name} .")
403
- @logger.info("Undeploying vApp #{vapp.name} .") if undeploy
404
- current_vapp = @connection.get(vapp)
405
- unless current_vapp
406
- raise ObjectNotFoundError, "vApp #{vapp.name} no longer exists."
407
- end
408
- @logger.debug("vApp status: #{current_vapp["status"]}")
409
-
410
- if is_vapp_status(current_vapp, :SUSPENDED)
411
- @logger.debug("vApp #{current_vapp.name} suspended, discard state " +
412
- "before powering off.")
413
- raise VappSuspendedError, "discard state first"
414
- end
415
-
416
- if undeploy
417
- # Since we do not apparently differentiate between powered-off and
418
- # undeployed in our status, we should check if the undeploy link is
419
- # available first. If undeploy is not available and status is
420
- # powered_off then it is undeployed.
421
- unless current_vapp.undeploy_link
422
- if is_vapp_status(current_vapp, :POWERED_OFF)
423
- @logger.info("vApp #{vapp.name} already powered-off, undeployed.")
424
- return
425
- end
426
- raise CloudError, "vApp #{vapp.name} not in a state be " +
427
- "powered-off, undeployed."
428
- end
429
- params = Xml::WrapperFactory.create_instance("UndeployVAppParams")
430
- task = @connection.post(current_vapp.undeploy_link, params)
431
- monitor_task(task, @time_limit["undeploy"])
432
- @logger.info("vApp #{current_vapp.name} powered-off, undeployed.")
433
- task
434
- else
435
- unless current_vapp.power_off_link
436
- if is_vapp_status(current_vapp, :POWERED_OFF)
437
- @logger.info("vApp #{vapp.name} already powered off.")
438
- return
439
- end
440
- raise CloudError, "vApp #{vapp.name} not in a state be powered off."
441
- end
442
- task = @connection.post(current_vapp.power_off_link, nil)
443
- monitor_task(task, @time_limit["power_off"])
444
- @logger.info("vApp #{current_vapp.name} powered off.")
445
- task
446
- end
447
- end
448
-
449
- def discard_suspended_state_vapp(vapp)
450
- @logger.info("Discarding suspended state of vApp #{vapp.name}.")
451
- current_vapp = @connection.get(vapp)
452
- unless current_vapp
453
- raise ObjectNotFoundError, "vApp #{vapp.name} no longer exists."
454
- end
455
- @logger.debug("vApp status: #{current_vapp["status"]}")
456
-
457
- return unless is_vapp_status(current_vapp, :SUSPENDED)
458
-
459
- @logger.info("Discarding suspended state of vApp #{current_vapp.name}.")
460
- task = @connection.post(current_vapp.discard_state, nil)
461
- monitor_task(task, @time_limit["undeploy"])
462
- current_vapp = @connection.get(current_vapp)
463
- @logger.info("vApp #{current_vapp.name} suspended state discarded.")
464
- task
465
- end
11
+ VCLOUD_VERSION_NUMBER = "5.1"
466
12
 
467
- def reboot_vapp(vapp)
468
- @logger.info("Rebooting vApp #{vapp.name}.")
469
- current_vapp = @connection.get(vapp)
470
- unless current_vapp
471
- raise ObjectNotFoundError, "vApp #{vapp.name} no longer exists."
472
- end
473
- @logger.debug("vApp status: #{current_vapp["status"]}")
13
+ public :find_vdc_by_name, :catalogs, :list_catalogs,
14
+ :catalog_exists?, :find_catalog_by_name
474
15
 
475
- if is_vapp_status(current_vapp, :SUSPENDED)
476
- @logger.debug("vApp #{current_vapp.name} suspended.")
477
- raise VappSuspendedError, "vapp suspended"
478
- end
479
- if is_vapp_status(current_vapp, :POWERED_OFF)
480
- @logger.debug("vApp #{current_vapp.name} powered off.")
481
- raise VappPoweredOffError, "vapp powered off"
482
- end
483
-
484
- @logger.info("Rebooting vApp #{current_vapp.name}.")
485
- task = @connection.post(current_vapp.reboot_link, nil)
486
- monitor_task(task)
487
- current_vapp = @connection.get(current_vapp)
488
- @logger.info("vApp #{current_vapp.name} rebooted.")
489
- task
490
- end
491
-
492
- def get_ovdc
493
- vdc = @admin_org.vdc(@ovdc_name)
494
- raise ObjectNotFoundError, "VDC #{@ovdc_name} not found." unless vdc
495
- @connection.get(vdc)
496
- end
497
-
498
- def get_catalog(name)
499
- catalog = @connection.get(@admin_org.catalog(name))
500
- end
501
-
502
- private
503
-
504
- ERROR_STATUSES = [Xml::TASK_STATUS[:ABORTED], Xml::TASK_STATUS[:ERROR],
505
- Xml::TASK_STATUS[:CANCELED]]
506
- SUCCESS_STATUS = [Xml::TASK_STATUS[:SUCCESS]]
507
-
508
- def resolve_entity(id)
509
- url = "#{@entity_resolver_link}#{id}"
510
- entity = @connection.get(url)
511
- raise ObjectNotFoundError, "Unable to get entity" unless entity
512
- @connection.get(entity.link)
513
- end
514
-
515
- def get_disk_id(vm, disk_href)
516
- hardware_section = vm.hardware_section
517
- disk = hardware_section.hard_disks.find do |d|
518
- d.host_resource["disk"] == disk_href
519
- end
520
- unless disk
521
- raise DiskNotFoundError, "Disk with href #{disk_href} not attached " +
522
- "to VM #{vm.name}."
523
- end
524
- disk.disk_id
525
- end
526
-
527
- def log_exception(e, message = nil)
528
- @logger.error(message) if message
529
- @logger.error(e.message)
530
- @logger.error(e.backtrace.join("\n\r"))
531
- end
532
-
533
- def copy_network_settings(network, network_config, vapp_net_name,
534
- fence_mode)
535
- config_ip_scope = network_config.ip_scope
536
- net_ip_scope = network.ip_scope
537
- config_ip_scope.is_inherited = net_ip_scope.is_inherited?
538
- config_ip_scope.gateway= net_ip_scope.gateway
539
- config_ip_scope.netmask = net_ip_scope.netmask
540
- if net_ip_scope.start_address
541
- config_ip_scope.start_address = net_ip_scope.start_address
542
- end
543
- if net_ip_scope.end_address
544
- config_ip_scope.end_address = net_ip_scope.end_address
545
- end
546
- network_config.fence_mode = fence_mode
547
- network_config.parent_network["name"] = network["name"]
548
- network_config.parent_network["href"] = network["href"]
549
- network_config["networkName"] = vapp_net_name
550
- end
551
-
552
- def delete_vapp_template(vapp_template)
553
- delete_vapp_or_template(vapp_template, @retries["default"],
554
- @time_limit["delete_vapp_template"], "vApp Template")
555
- end
556
-
557
- def check_vapp_for_remove_link(vapp)
558
- current_vapp = @connection.get(vapp)
559
- unless current_vapp.remove_link
560
- raise ObjectNotFoundError, "No link available to delete vApp."
561
- end
562
- return current_vapp
563
- end
564
-
565
- def delete_vapp_or_template(vapp, retries, time_limit, type_name)
566
- retries.times do |try|
567
- @logger.info("Deleting #{type_name} #{vapp.name}")
568
- current_vapp = @connection.get(vapp)
569
- if (current_vapp.running_tasks.empty?)
570
- Util.retry_operation(current_vapp, @retries["default"],
571
- @control["backoff"]) do
572
- current_vapp = check_vapp_for_remove_link(current_vapp)
573
- end
574
- Util.retry_operation(current_vapp.remove_link, @retries["default"],
575
- @control["backoff"]) do
576
- monitor_task(@connection.delete(current_vapp.remove_link),
577
- time_limit) do |task|
578
- @logger.info("#{type_name} #{current_vapp.name} deleted.")
579
- return task
580
- end
581
- end
582
- else
583
- @logger.info("#{vapp.name} has tasks in progress, wait until done.")
584
- current_vapp.running_tasks.each do |task|
585
- monitor_task(task)
586
- end
587
- sleep (@control["backoff"] ** try)
588
- end
589
- end
590
- raise ApiRequestError,
591
- "Unable to delete #{type_name} after #{retries} attempts"
592
- end
593
-
594
- def insert_media(vm, media, retries = @retries["default"])
595
- params = Xml::WrapperFactory.create_instance("MediaInsertOrEjectParams")
596
- params.media_href = media.href
597
-
598
- # Wait for media to be ready
599
- retries.times do |try|
600
- @logger.info("Inserting media #{media.name} into VM #{vm.name}.")
601
- current_media = @connection.get(media)
602
- if (current_media.running_tasks.empty?)
603
- Util.retry_operation(vm.insert_media_link, @retries["default"],
604
- @control["backoff"]) do
605
- task = @connection.post(vm.insert_media_link, params,
606
- Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS])
607
- monitor_task(task) do |t|
608
- raise CloudError, "Error inserting media #{media.name} " +
609
- "into VM #{vm.name}." if t.status != "success"
610
- @logger.info("Inserted media #{media.name} into VM #{vm.name}.")
611
- return t
612
- end
613
- end
614
- else
615
- @logger.info("#{current_media.name} has tasks in progress, " +
616
- "waiting until done.")
617
- current_media.running_tasks.each do |task|
618
- monitor_task(task)
619
- end
620
- sleep (@control["backoff"] ** try)
621
- end
622
- end
623
- raise ApiRequestError, "Unable to insert media #{media.name} into " +
624
- "VM #{vm.name} after #{retries} attempts"
625
- end
626
-
627
- def eject_media(vm, media, retries = @retries["default"])
628
- params = Xml::WrapperFactory.create_instance("MediaInsertOrEjectParams")
629
- params.media_href = media.href
630
-
631
- #Wait for media to be ready
632
- retries.times do |try|
633
- @logger.info("Ejecting media #{media.name} from VM #{vm.name}.")
634
- current_media = @connection.get(media)
635
- if (current_media.running_tasks.empty?)
636
- return eject_media_task(vm, params, media)
637
- else
638
- @logger.info("#{current_media.name} has tasks in progress, " +
639
- "waiting until done.")
640
- current_media.running_tasks.each do |task|
641
- monitor_task(task)
642
- end
643
- sleep (@control["backoff"] ** try)
644
- end
645
- end
646
- raise ApiRequestError, "Unable to eject media #{media.name} from " +
647
- "VM #{vm.name} after #{retries} attempts"
648
- end
16
+ def initialize(url, username, password, options = {}, logger = nil)
17
+ @url = url
18
+ Config.configure(logger: logger || Logger.new(STDOUT))
649
19
 
650
- def delete_media(media, retries = @retries["default"],
651
- time_limit = @time_limit["delete_media"])
652
- retries.times do |try|
653
- @logger.info("Deleting media #{media.name}")
654
- current_media = @connection.get(media)
655
- if (current_media.running_tasks.empty?)
656
- Util.retry_operation(current_media.delete_link, @retries["default"],
657
- @control["backoff"]) do
658
- monitor_task(@connection.delete(current_media.delete_link),
659
- time_limit) do |task|
660
- @logger.info("Media #{current_media.name} deleted.")
661
- return task
662
- end
663
- end
664
- else
665
- @logger.info("#{current_media.name} has tasks in progress, " +
666
- "waiting until done.")
667
- current_media.running_tasks.each do |task|
668
- monitor_task(task)
669
- end
670
- sleep (@control["backoff"] ** try)
671
- end
672
- end
673
- raise ApiRequestError, "Unable to delete #{type_name} after "
674
- "#{retries} attempts"
20
+ @session = Session.new(url, username, password, options)
21
+ Config.logger.info("Successfully connected.")
675
22
  end
676
23
 
677
- def get_catalog_media(name)
678
- get_catalog_item(name, Xml::MEDIA_TYPE[:MEDIA], @media_catalog_name)
24
+ def create_catalog(name, description = "")
25
+ catalog = Xml::WrapperFactory.create_instance("AdminCatalog")
26
+ catalog.name = name
27
+ catalog.description = description
28
+ connection.post("/api/admin/org/#{@session.org.href_id}/catalogs",
29
+ catalog,
30
+ Xml::ADMIN_MEDIA_TYPE[:CATALOG])
31
+ find_catalog_by_name name
679
32
  end
680
33
 
681
- # Get catalog item from catalog by name and type.
682
- # Raises an exception if catalog is not found.
683
- # Returns nil if an item matching the name and type is not found.
684
- # Otherwise, returns the catalog item.
685
- # The catalog item is not the uderlying object itself, i.e. vApp template.
686
- def get_catalog_item(name, item_type, catalog_name)
687
- raise ObjectNotFoundError, "Catalog item name cannot be nil" unless name
688
- unless @admin_org.catalog(catalog_name)
689
- raise ObjectNotFoundError, "Catalog #{catalog_name} not found."
690
- end
691
- # For some reason, if the catalog no longer exists,
692
- # VCD throws a Forbidden exception when getting
693
- catalog = @connection.get(@admin_org.catalog(catalog_name))
694
- items = catalog.catalog_items(name)
695
- if items.nil? || items.empty?
696
- @logger.debug("Item #{name} does not exist in catalog #{catalog_name}")
697
- return nil
698
- end
699
- items.each do |i|
700
- entity = @connection.get(i)
701
- # Return the entity node. Another get on that node is necessary to
702
- # get the actual object itself
703
- return entity if entity.entity["type"] == item_type
704
- end
34
+ def delete_catalog(name)
35
+ catalog = find_catalog_by_name(name)
36
+ catalog.delete_all_items
37
+ connection.delete("/api/admin/catalog/#{catalog.id}")
705
38
  nil
706
39
  end
707
-
708
- def get_vm_network_connections(vm)
709
- current_vm = @connection.get(vm)
710
- unless current_vm
711
- raise ObjectNotFoundError, "VM #{vm.name} no longer exists."
712
- end
713
- @connection.get(current_vm.network_connection_section)
714
- end
715
-
716
- def task_progressed?(current_task, prev_progress, prev_status)
717
- (current_task.progress && (current_task.progress != prev_progress)) ||
718
- (current_task.status && (current_task.status != prev_status))
719
- end
720
-
721
- def task_is_success(current_task, success = SUCCESS_STATUS)
722
- success.map { |s| s.downcase }.find {
723
- |s| s == current_task.status.downcase }
724
- end
725
-
726
- def task_has_error(current_task, error_statuses = ERROR_STATUSES)
727
- error_statuses.map { |s| s.downcase }.find {
728
- |s| s == current_task.status.downcase }
729
- end
730
-
731
- def monitor_task(task, time_limit = @time_limit["default"],
732
- error_statuses = ERROR_STATUSES, success = SUCCESS_STATUS,
733
- delay = @control["delay"], &b)
734
- iterations = time_limit / delay
735
- i = 0
736
- prev_progress = task.progress
737
- prev_status = task.status
738
- current_task = task
739
- while (i < iterations)
740
- @logger.debug("#{current_task.urn} #{current_task.operation} is " +
741
- "#{current_task.status}")
742
- if task_is_success(current_task, success)
743
- if b
744
- return b.call(current_task)
745
- else
746
- return current_task
747
- end
748
- elsif task_has_error(current_task, error_statuses)
749
- raise ApiRequestError, "Task #{task.urn} #{task.operation} did " +
750
- "not complete successfully."
751
- elsif task_progressed?(current_task, prev_progress, prev_status)
752
- @logger.debug("task status #{prev_status} => " +
753
- "#{current_task.status}, progress #{prev_progress}%" +
754
- " => #{current_task.progress}%, timer #{i} reset.")
755
- prev_progress = current_task.progress
756
- prev_status = current_task.status
757
- i = 0 #reset clock if status changes or running task makes progress
758
- sleep(delay)
759
- else
760
- @logger.debug("Approximately #{i * delay}s elapsed waiting for " +
761
- "#{current_task.operation} to reach " +
762
- "#{success.join("/")}/#{error_statuses.join("/")}." +
763
- " Checking again in #{delay} seconds.")
764
- @logger.debug("Task #{task.urn} progress: " +
765
- "#{current_task.progress} %.") if current_task.progress
766
- sleep(delay)
767
- end
768
- current_task = @connection.get(task)
769
- i += 1
770
- end
771
- raise ApiTimeoutError, "Task #{task.operation} did not complete " +
772
- "within limit of #{time_limit} seconds."
773
- end
774
-
775
-
776
- # TODO use times.upload_vapp_files
777
- def upload_vapp_files(vapp, ovf_directory,
778
- tries = @retries["upload_vapp_files"], try = 0)
779
- current_vapp = @connection.get(vapp)
780
- return current_vapp if !current_vapp.files || current_vapp.files.empty?
781
-
782
- @logger.debug("vapp files left to upload #{current_vapp.files}.")
783
- @logger.debug("vapp incomplete files left to upload " +
784
- "#{current_vapp.incomplete_files}.")
785
- raise ApiTimeoutError, "Unable to finish uploading vApp after " +
786
- "#{tries} tries #{current_vapp.files}." if tries == try
787
-
788
- current_vapp.incomplete_files.each do |f|
789
- # switch on extension
790
- case f.name.split(".").pop.downcase
791
- when "ovf"
792
- @logger.info("Uploading OVF file: " +
793
- "#{ovf_directory.ovf_file_path} for #{vapp.name}")
794
- @connection.put(f.upload_link, ovf_directory.ovf_file.read,
795
- Xml::MEDIA_TYPE[:OVF])
796
- when "vmdk"
797
- @logger.info("Uploading VMDK file " +
798
- "#{ovf_directory.vmdk_file_path(f.name)} for #{vapp.name}")
799
- @connection.put_file(f.upload_link,
800
- ovf_directory.vmdk_file(f.name))
801
- end
802
- end
803
- #repeat
804
- sleep (2 ** try)
805
- upload_vapp_files(current_vapp, ovf_directory, tries, try + 1)
806
- end
807
-
808
- def add_catalog_item(item, catalog_name)
809
- unless @admin_org.catalog(catalog_name)
810
- raise ArgumentError,
811
- "Error adding #{item.name}, catalog #{catalog_name} not found."
812
- end
813
- catalog = @connection.get(@admin_org.catalog(catalog_name))
814
- raise ObjectNotFoundError, "Error adding #{item.name}, catalog " +
815
- "#{catalog_name} not available." unless catalog
816
- catalog_item = Xml::WrapperFactory.create_instance("CatalogItem")
817
- catalog_item.name = item.name
818
- catalog_item.entity = item
819
- @logger.info("Adding #{catalog_item.name} to catalog #{catalog_name}")
820
- @connection.post(catalog.add_item_link, catalog_item,
821
- Xml::ADMIN_MEDIA_TYPE[:CATALOG_ITEM])
822
- end
823
-
824
- def generate_metadata_href(entity, key)
825
- raise ObjectNotFoundError, "Entity #{entity.name} does not expose a " +
826
- "metadata link method." if !entity.respond_to?(:metadata_link)
827
- "#{entity.metadata_link.href}/#{key}"
828
- end
829
-
830
- def get_vapp_by_name(name)
831
- @logger.debug("Getting vApp #{name}")
832
- vdc = get_ovdc
833
- node = vdc.get_vapp(name)
834
- raise ObjectNotFoundError, "vApp #{name} does not exist." unless node
835
- vapp = @connection.get(node)
836
- raise ObjectNotFoundError, "vApp #{name} does not exist." unless vapp
837
- vapp
838
- end
839
-
840
- def locality_spec(src_vapp_template, disk_locality)
841
- disk_locality ||= []
842
- locality = {}
843
- disk_locality.each do |disk|
844
- current_disk = @connection.get(disk)
845
- unless current_disk
846
- @logger.warn("Disk #{disk.name} no longer exists.")
847
- next
848
- end
849
- src_vapp_template.vms.each do |vm|
850
- locality[vm] = current_disk
851
- end
852
- end
853
- locality
854
- end
855
-
856
- def is_vapp_status(current_vapp, status)
857
- current_vapp["status"] == Xml::RESOURCE_ENTITY_STATUS[status].to_s
858
- end
859
-
860
- def rollback_upload_vapp(vapp_template)
861
- @logger.error("Rolling back changes.")
862
- begin
863
- delete_vapp_template(vapp_template) if vapp_template
864
- rescue => rollbackex
865
- log_exception(rollbackex, "Error in rolling back failed vApp " +
866
- "template #{vapp_name}.")
867
- end
868
- end
869
-
870
- def eject_media_task(vm, params, media)
871
- Util.retry_operation(vm.eject_media_link, @retries["default"],
872
- @control["backoff"]) do
873
- task = @connection.post(vm.eject_media_link, params,
874
- Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS])
875
- monitor_task(task) do |t|
876
- if t.status != "success"
877
- raise CloudError, "Error ejecting media #{media.name} from " +
878
- "VM #{vm.name}."
879
- end
880
- @logger.info("Ejected media #{media.name} from VM #{vm.name}.")
881
- return t
882
- end
883
- end
884
- end
885
-
886
- def construct_rest_logger
887
- @logger.debug("constructing rest_logger")
888
- rest_log_filename = File.join(File.dirname(@logger.instance_eval {
889
- @logdev }.dev.path), "rest")
890
- log_file = File.open(rest_log_filename, "w")
891
- log_file.sync = true
892
-
893
- @rest_logger = Logger.new(log_file || STDOUT)
894
- @rest_logger.level = @logger.level
895
- @rest_logger.formatter = @logger.formatter
896
- end
897
40
  end
898
41
 
899
42
  end