opennebula 5.12.6 → 5.13.90.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ActionManager.rb +1 -1
  3. data/lib/CommandManager.rb +1 -1
  4. data/lib/DriverExecHelper.rb +44 -28
  5. data/lib/OpenNebulaDriver.rb +8 -4
  6. data/lib/VirtualMachineDriver.rb +9 -2
  7. data/lib/cloud/CloudClient.rb +3 -3
  8. data/lib/datacenter.rb +1259 -0
  9. data/lib/datastore.rb +1025 -0
  10. data/lib/distributed_firewall.rb +280 -0
  11. data/lib/file_helper.rb +370 -0
  12. data/lib/host.rb +1517 -0
  13. data/lib/logical_port.rb +50 -0
  14. data/lib/logical_switch.rb +77 -0
  15. data/lib/memoize.rb +74 -0
  16. data/lib/models.rb +32 -0
  17. data/lib/models/role.rb +1126 -0
  18. data/lib/models/service.rb +709 -0
  19. data/lib/network.rb +708 -0
  20. data/lib/nsx_client.rb +144 -0
  21. data/lib/nsx_component.rb +28 -0
  22. data/lib/nsx_constants.rb +149 -0
  23. data/lib/nsx_driver.rb +78 -0
  24. data/lib/nsx_error.rb +77 -0
  25. data/lib/nsx_rule.rb +193 -0
  26. data/lib/nsxt_client.rb +176 -0
  27. data/lib/nsxt_dfw.rb +196 -0
  28. data/lib/nsxt_logical_port.rb +94 -0
  29. data/lib/nsxt_rule.rb +188 -0
  30. data/lib/nsxt_tz.rb +38 -0
  31. data/lib/nsxv_client.rb +176 -0
  32. data/lib/nsxv_dfw.rb +202 -0
  33. data/lib/nsxv_logical_port.rb +107 -0
  34. data/lib/nsxv_rule.rb +172 -0
  35. data/lib/nsxv_tz.rb +41 -0
  36. data/lib/opaque_network.rb +134 -0
  37. data/lib/opennebula.rb +5 -2
  38. data/lib/opennebula/acl.rb +1 -1
  39. data/lib/opennebula/acl_pool.rb +1 -1
  40. data/lib/opennebula/client.rb +10 -2
  41. data/lib/opennebula/cluster.rb +1 -1
  42. data/lib/opennebula/cluster_pool.rb +1 -1
  43. data/lib/opennebula/datastore.rb +1 -1
  44. data/lib/opennebula/datastore_pool.rb +1 -1
  45. data/lib/opennebula/document.rb +8 -29
  46. data/lib/opennebula/document_json.rb +42 -12
  47. data/lib/opennebula/document_pool.rb +1 -1
  48. data/lib/opennebula/document_pool_json.rb +1 -1
  49. data/lib/opennebula/error.rb +4 -1
  50. data/lib/opennebula/flow.rb +23 -0
  51. data/lib/opennebula/flow/grammar.rb +1195 -0
  52. data/lib/opennebula/flow/service_pool.rb +190 -0
  53. data/lib/opennebula/flow/service_template.rb +572 -0
  54. data/lib/opennebula/flow/service_template_ext.rb +84 -0
  55. data/lib/opennebula/flow/service_template_pool.rb +32 -0
  56. data/lib/opennebula/flow/validator.rb +499 -0
  57. data/lib/opennebula/group.rb +1 -1
  58. data/lib/opennebula/group_pool.rb +1 -1
  59. data/lib/opennebula/hook.rb +5 -12
  60. data/lib/opennebula/hook_log.rb +1 -1
  61. data/lib/opennebula/hook_pool.rb +1 -1
  62. data/lib/opennebula/host.rb +1 -1
  63. data/lib/opennebula/host_pool.rb +1 -1
  64. data/lib/opennebula/image.rb +19 -14
  65. data/lib/opennebula/image_pool.rb +1 -1
  66. data/lib/opennebula/ldap_auth.rb +1 -1
  67. data/lib/opennebula/ldap_auth_spec.rb +1 -1
  68. data/lib/opennebula/lockable_ext.rb +163 -0
  69. data/lib/opennebula/marketplace.rb +1 -1
  70. data/lib/opennebula/marketplace_pool.rb +1 -1
  71. data/lib/opennebula/marketplaceapp.rb +9 -119
  72. data/lib/opennebula/marketplaceapp_ext.rb +522 -0
  73. data/lib/opennebula/marketplaceapp_pool.rb +1 -1
  74. data/lib/opennebula/oneflow_client.rb +4 -3
  75. data/lib/opennebula/pool.rb +19 -3
  76. data/lib/opennebula/pool_element.rb +1 -1
  77. data/lib/opennebula/security_group.rb +1 -1
  78. data/lib/opennebula/security_group_pool.rb +1 -1
  79. data/lib/opennebula/server_cipher_auth.rb +1 -1
  80. data/lib/opennebula/server_x509_auth.rb +1 -1
  81. data/lib/opennebula/ssh_auth.rb +1 -1
  82. data/lib/opennebula/system.rb +1 -1
  83. data/lib/opennebula/template.rb +4 -13
  84. data/lib/opennebula/template_ext.rb +342 -0
  85. data/lib/opennebula/template_pool.rb +1 -1
  86. data/lib/opennebula/user.rb +26 -2
  87. data/lib/opennebula/user_pool.rb +1 -1
  88. data/lib/opennebula/utils.rb +1 -1
  89. data/lib/opennebula/vdc.rb +1 -1
  90. data/lib/opennebula/vdc_pool.rb +1 -1
  91. data/lib/opennebula/virtual_machine.rb +26 -206
  92. data/lib/opennebula/virtual_machine_ext.rb +469 -0
  93. data/lib/opennebula/virtual_machine_pool.rb +5 -1
  94. data/lib/opennebula/virtual_network.rb +4 -10
  95. data/lib/opennebula/virtual_network_pool.rb +1 -1
  96. data/lib/opennebula/virtual_router.rb +4 -12
  97. data/lib/opennebula/virtual_router_pool.rb +1 -1
  98. data/lib/opennebula/vm_group.rb +4 -11
  99. data/lib/opennebula/vm_group_pool.rb +1 -1
  100. data/lib/opennebula/vntemplate.rb +4 -13
  101. data/lib/opennebula/vntemplate_pool.rb +1 -1
  102. data/lib/opennebula/wait_ext.rb +257 -0
  103. data/lib/opennebula/x509_auth.rb +1 -1
  104. data/lib/opennebula/xml_element.rb +1 -1
  105. data/lib/opennebula/xml_pool.rb +1 -1
  106. data/lib/opennebula/xml_utils.rb +1 -1
  107. data/lib/opennebula/zone.rb +1 -1
  108. data/lib/opennebula/zone_pool.rb +1 -1
  109. data/lib/rest_client.rb +201 -0
  110. data/lib/scripts_common.rb +180 -0
  111. data/lib/transport_zone.rb +43 -0
  112. data/lib/vcenter_driver.rb +13 -12
  113. data/lib/vcenter_importer.rb +616 -0
  114. data/lib/vi_client.rb +281 -0
  115. data/lib/vi_helper.rb +312 -0
  116. data/lib/virtual_machine.rb +3477 -0
  117. data/lib/virtual_wire.rb +158 -0
  118. data/lib/vm_device.rb +80 -0
  119. data/lib/vm_disk.rb +202 -0
  120. data/lib/vm_folder.rb +69 -0
  121. data/lib/vm_helper.rb +30 -0
  122. data/lib/vm_monitor.rb +303 -0
  123. data/lib/vm_nic.rb +70 -0
  124. data/lib/vm_template.rb +1961 -0
  125. data/lib/vmm_importer.rb +121 -0
  126. metadata +130 -17
@@ -0,0 +1,522 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ # Module to decorate MarketApp class with additional helpers not directly
18
+ # exposed through the OpenNebula XMLRPC API. The extensions include
19
+ # - export helper that creates OpenNebula related objects from a given app.
20
+ #
21
+ # rubocop:disable Style/ClassAndModuleChildren
22
+ module OpenNebula::MarketPlaceAppExt
23
+
24
+ include OpenNebula
25
+
26
+ def self.extend_object(obj)
27
+ if !obj.is_a?(OpenNebula::MarketPlaceApp)
28
+ raise StandardError, "Cannot extended #{obj.class} " \
29
+ 'with MarketPlaceAppExt'
30
+ end
31
+
32
+ class << obj
33
+
34
+ ####################################################################
35
+ # Public extended interface
36
+ ####################################################################
37
+ # Exports this app to a suitable OpenNebula object
38
+ # @param appid [Integer] id of the marketplace app
39
+ # @param options [Hash] to control the export behavior
40
+ # dsid [Integer] datastore to save images
41
+ # f_dsid [Integer] file datastore to save kernels
42
+ # name [String] of the new object
43
+ # vmtemplate_name [String] name for the VM Template, if the App
44
+ # has one complex [Boolean] true to only create image
45
+ #
46
+ # @return [Hash, OpenNebula::Error] with the ID and type of
47
+ # the created objects. Instead of an ID, the array may
48
+ # contain OpenNebula::Error with specific object creation errors
49
+ # {
50
+ # :vm => [ vm ids/OpenNebula::Error ],
51
+ # :vmtemplate => [ vmtemplates ids/OpenNebula::Error ],
52
+ # :image => [ vm ids/OpenNebula::Error ]
53
+ # }
54
+ # rc_info = {
55
+ # :image => [],
56
+ # :image_type => nil,
57
+ # :vmtemplate => [],
58
+ # :service_template => []
59
+ # }
60
+ def export(options = {})
61
+ # Get App information and check for errors
62
+ rc = info
63
+ return rc if OpenNebula.is_error?(rc)
64
+ return Error.new('App is not READY') if state_str != 'READY'
65
+
66
+ if options[:dsid].nil?
67
+ return Error.new('Missing datastore id')
68
+ end
69
+
70
+ if options[:name].nil?
71
+ return Error.new('Missing name to export app')
72
+ end
73
+
74
+ case type_str
75
+ when 'IMAGE'
76
+ export_image(options)
77
+ when 'VMTEMPLATE'
78
+ options[:notemplate] = true
79
+
80
+ export_vm_template(options)
81
+ when 'SERVICE_TEMPLATE'
82
+ export_service_template(options)
83
+ else
84
+ Error.new("App type #{type_str} not supported")
85
+ end
86
+ end
87
+
88
+ ####################################################################
89
+ # Private methods
90
+ ####################################################################
91
+ private
92
+
93
+ # Exports an OpenNebula Image from this marketplace app
94
+ # @param options to export the image
95
+ # :vmtemplate_name [String] name of new image and template
96
+ # :url_args [String] optional URL arguments
97
+ # :dsid [String] Datastore id to create the image
98
+ # :f_dsid [String] Files Datastore id
99
+ # :notemplate [Bool] if true do not create vm_template (if any)
100
+ # :template [Integer] Template id to use with image
101
+ # :default_template [String] Default template id for vCenter
102
+ # @return [Hash]
103
+ # :image [Array] of the new image
104
+ # :image_type [String] of the new image (CONTEXT, KERNEL, CDROM)
105
+ # :vmtemplate [Array] of the associated vm_template (if any)
106
+ # :service_template [Array] empty []
107
+ def export_image(options)
108
+ rc_info = {
109
+ :image => [],
110
+ :image_type => nil,
111
+ :vmtemplate => [],
112
+ :service_template => []
113
+ }
114
+
115
+ #---------------------------------------------------------------
116
+ # Create the image template
117
+ #---------------------------------------------------------------
118
+ tmpl = ''
119
+
120
+ if self['APPTEMPLATE64']
121
+ tmpl = Base64.decode64(self['APPTEMPLATE64'])
122
+ end
123
+
124
+ tmpl << <<-EOT
125
+ NAME = "#{options[:name]}"
126
+ FROM_APP = "#{self['ID']}"
127
+ EOT
128
+
129
+ if options[:url_args]
130
+ tmpl << "URL_ARGS=\"#{options[:url_args]}\"\n"
131
+ end
132
+
133
+ #---------------------------------------------------------------
134
+ # Kernel or context images stored in a files datastore
135
+ #---------------------------------------------------------------
136
+ dsid = options[:dsid]
137
+
138
+ if tmpl.match(/^\s*TYPE\s*=\s*KERNEL|CONTEXT\s/i)
139
+ if options[:f_dsid]
140
+ dsid = options[:f_dsid]
141
+ else
142
+ dspool = DatastorePool.new(@client)
143
+
144
+ rc = dspool.info
145
+ return { :image => [rc] } if OpenNebula.is_error?(rc)
146
+
147
+ file_ds = dspool.select {|d| d['TYPE'].to_i == 2 }
148
+ dsid = file_ds.first['ID'].to_i
149
+ end
150
+ end
151
+
152
+ ds = OpenNebula::Datastore.new_with_id(dsid, @client)
153
+ rc = ds.info
154
+
155
+ is_vcenter = !OpenNebula.is_error?(rc) &&
156
+ (ds['TEMPLATE/DRIVER'] == 'vcenter')
157
+
158
+ #---------------------------------------------------------------
159
+ # Allocate the image in OpenNebula
160
+ #---------------------------------------------------------------
161
+ image = Image.new(Image.build_xml, @client)
162
+ rc = image.allocate(tmpl, dsid)
163
+
164
+ if OpenNebula.is_error?(rc)
165
+ rc_info[:image] = [rc]
166
+
167
+ return rc_info
168
+ end
169
+
170
+ image.info
171
+
172
+ image.delete_element('TEMPLATE/FORMAT')
173
+ image.delete_element('TEMPLATE/DRIVER')
174
+ image.delete_element('TEMPLATE/DEV_PREFIX') if is_vcenter
175
+
176
+ image.update(image.template_xml)
177
+
178
+ rc_info[:image] = [image.id]
179
+ rc_info[:image_type] = image.type_str
180
+
181
+ #---------------------------------------------------------------
182
+ # Created an associated VMTemplate if needed
183
+ #---------------------------------------------------------------
184
+ if self['TEMPLATE/VMTEMPLATE64'].nil? || options[:notemplate]
185
+ return rc_info
186
+ end
187
+
188
+ if !options[:template].nil?
189
+ template_id = options[:template]
190
+
191
+ if template_id == -1
192
+ template_id = options[:default_template]
193
+ end
194
+
195
+ template = Template.new_with_id(template_id, @client)
196
+
197
+ vmtpl_id = template.clone(
198
+ options[:vmtemplate_name] || options[:name]
199
+ )
200
+
201
+ tmpl << <<-EOT
202
+
203
+ NAME = "#{options[:vmtemplate_name] || options[:name]}"
204
+ DISK = [ IMAGE_ID = "#{image.id}" ]
205
+ EOT
206
+
207
+ template = Template.new_with_id(vmtpl_id, @client)
208
+
209
+ template.update(tmpl, true)
210
+
211
+ rc_info[:vmtemplate] = [vmtpl_id]
212
+ else
213
+ tmpl = Base64.decode64(self['TEMPLATE/VMTEMPLATE64'])
214
+ tmpl << <<-EOT
215
+
216
+ NAME = "#{options[:vmtemplate_name] || options[:name]}"
217
+ DISK = [ IMAGE_ID = "#{image.id}" ]
218
+ EOT
219
+
220
+ vmtpl = Template.new(Template.build_xml, @client)
221
+
222
+ rc = vmtpl.allocate(tmpl)
223
+ rc = vmtpl.id unless OpenNebula.is_error?(rc)
224
+
225
+ rc_info[:vmtemplate] = [rc]
226
+ end
227
+
228
+ rc_info
229
+ end
230
+
231
+ # Export complex template from marketplace
232
+ #
233
+ # @param name [Hash] Export options
234
+ # @param ds_id [Integer] Datastore ID to export child apps
235
+ def export_vm_template(options)
236
+ rc = {
237
+ :image => [],
238
+ :image_type => nil,
239
+ :vmtemplate => [],
240
+ :service_template => []
241
+ }
242
+
243
+ vmtmpl = export_recursive('//DISK', options) do |disks|
244
+ create_vm_template(options, disks)
245
+ end
246
+
247
+ rc[:vmtemplate] = [vmtmpl[0]]
248
+
249
+ unless OpenNebula.is_error?(vmtmpl[0])
250
+ rc[:image] += vmtmpl[1]
251
+ rc[:vmtemplate] += vmtmpl[2] unless options[:notemplate]
252
+ end
253
+
254
+ rc
255
+ end
256
+
257
+ # Export service template from marketplace
258
+ #
259
+ # @param name [Hash] Export options
260
+ # @param ds_id [Integer] Datastore ID to export child apps
261
+ def export_service_template(options)
262
+ rc = {
263
+ :image => [],
264
+ :image_type => nil,
265
+ :vmtemplate => [],
266
+ :service_template => []
267
+ }
268
+
269
+ stmpl = export_recursive('//ROLE', options) do |roles|
270
+ create_service_template(options, roles)
271
+ end
272
+
273
+ rc[:service_template] = [stmpl[0]]
274
+
275
+ unless OpenNebula.is_error?(stmpl[0])
276
+ rc[:image] += stmpl[1]
277
+ rc[:vmtemplate] += stmpl[2]
278
+ end
279
+
280
+ rc
281
+ end
282
+
283
+ # Creates a VM template based on the APPTEMPLATE64 attribute
284
+ # @param [Hash] options
285
+ # :export_name [String] name of the vm template
286
+ # @param [Hash] disks exported disks from related apps.
287
+ # As returned by the export_image method
288
+ #
289
+ # @return [Integer, OpenNebula::Error] template id or error
290
+ def create_vm_template(options, disks)
291
+ # --------------------------------------------------------------
292
+ # Allocate Template
293
+ # --------------------------------------------------------------
294
+ if self['TEMPLATE/APPTEMPLATE64'].nil?
295
+ return Error.new("Missing APPTEMPLATE64 for App #{id}")
296
+ end
297
+
298
+ tmpl = Base64.decode64(self['TEMPLATE/APPTEMPLATE64'])
299
+
300
+ tmpl << "\nNAME=\"#{options[:name]}\"\n"
301
+
302
+ vmtpl = Template.new(Template.build_xml, @client)
303
+ rc = vmtpl.allocate(tmpl)
304
+
305
+ return rc if OpenNebula.is_error?(rc)
306
+
307
+ # --------------------------------------------------------------
308
+ # Update disk information in template
309
+ # --------------------------------------------------------------
310
+ vmtpl.info
311
+
312
+ context = []
313
+
314
+ disks.each do |_app, disk|
315
+ id = disk[:image]
316
+
317
+ case disk[:image_type]
318
+ when 'IMAGE', 'OS', 'DATABLOCK', 'CDROM'
319
+ vmtpl.add_element('TEMPLATE',
320
+ 'DISK' => { 'IMAGE_ID' => id.first })
321
+ when 'CONTEXT'
322
+ context << "$FILE[IMAGE_ID=\"#{id}\"]"
323
+ when 'KERNEL'
324
+ if !vmtpl.has_elements?('TEMPLATE/OS')
325
+ vmtpl.add_element('TEMPLATE', 'OS'=>{})
326
+ end
327
+
328
+ vmtpl.add_element(
329
+ 'TEMPLATE/OS',
330
+ 'KERNEL_DS' => "$FILE[IMAGE_ID=#{id}]"
331
+ )
332
+ end
333
+ end
334
+
335
+ if !context.empty?
336
+ if !vmtpl.has_elements?('TEMPLATE/CONTEXT')
337
+ vmtpl.add_element('TEMPLATE', 'CONTEXT' => {})
338
+ end
339
+
340
+ vmtpl.add_element('TEMPLATE/CONTEXT',
341
+ 'FILES_DS' => context.join(' '))
342
+ end
343
+
344
+ # --------------------------------------------------------------
345
+ # Update template information in OpenNebula
346
+ # --------------------------------------------------------------
347
+ vmtpl.update(vmtpl.template_xml)
348
+
349
+ vmtpl.id
350
+ end
351
+
352
+ # Creates a Service template based on the VMTEMPLATE64 attribute
353
+ # @return [Integer, OpenNebula::Error] template id or error
354
+ def create_service_template(options, roles)
355
+ # --------------------------------------------------------------
356
+ # Allocate Template
357
+ # --------------------------------------------------------------
358
+ if self['TEMPLATE/APPTEMPLATE64'].nil?
359
+ return Error.new("Missing APPTEMPLATE64 for App #{id}")
360
+ end
361
+
362
+ tmpl = Base64.decode64(self['TEMPLATE/APPTEMPLATE64'])
363
+ tmpl = JSON.parse(tmpl)
364
+
365
+ tmpl['name'] = options[:name]
366
+
367
+ # --------------------------------------------------------------
368
+ # Append template IDs to each role information
369
+ # --------------------------------------------------------------
370
+ tmpl['roles'].each do |role|
371
+ t_id = roles.find {|_, v| v[:names].include?(role['name']) }
372
+
373
+ if t_id.nil? || t_id[1].nil? || t_id[1][:vmtemplate].nil?
374
+ next
375
+ end
376
+
377
+ role['vm_template'] = nil
378
+ role['vm_template'] = t_id[1][:vmtemplate][0]
379
+ end
380
+
381
+ # --------------------------------------------------------------
382
+ # Allocate Service template in OpenNebula
383
+ # --------------------------------------------------------------
384
+ stmpl = ServiceTemplate.new(ServiceTemplate.build_xml, @client)
385
+
386
+ rc = stmpl.allocate(tmpl.to_json)
387
+ rc = stmpl.id unless OpenNebula.is_error?(rc)
388
+
389
+ rc
390
+ end
391
+
392
+ # Export complex template from marketplace
393
+ #
394
+ # @param xpath [String] Xpath to search childs
395
+ # @param options [Hash] Export options
396
+ # @param ds_id [Integer] Datastore ID to export child apps
397
+ def export_recursive(xpath, options)
398
+ # Get marketplace apps pool to find roles apps
399
+ pool = OpenNebula::MarketPlaceAppPool.new(@client)
400
+ rc = pool.info
401
+
402
+ return rc if OpenNebula.is_error?(rc)
403
+
404
+ # Apps that have been already exported
405
+ #
406
+ # app_name =>
407
+ # :vmtempalte = exported template ID
408
+ # :image = exported image ID
409
+ # :image_type = type (KERNEL, CONTEXT...) of image
410
+ # :names = [name_a, name_b, ...]
411
+ exported = {}
412
+ idx = 0
413
+
414
+ # Store IDs of created resources
415
+ images = []
416
+ templates = []
417
+
418
+ # Iterate over all childs
419
+ rc = retrieve_xmlelements(xpath).each do |obj|
420
+ # Get name and app information
421
+ obj_name = obj['NAME']
422
+ app = obj['APP']
423
+
424
+ # If the app was already exported, do not export it again
425
+ if exported[app]
426
+ exported[app][:names] << obj_name
427
+ next
428
+ end
429
+
430
+ # Find app in pool
431
+ obj = pool.find {|p| p['NAME'] == app }
432
+
433
+ break Error.new("App `#{app}` not found") unless obj
434
+
435
+ obj.extend(MarketPlaceAppExt)
436
+
437
+ rc = obj.export(
438
+ :dsid => options[:dsid],
439
+ :name => "#{options[:name]}-#{idx}",
440
+ :notemplate => options[:notemplate]
441
+ )
442
+
443
+ image = rc[:image].first if rc[:image]
444
+ vmtemplate = rc[:vmtemplate].first if rc[:vmtemplate]
445
+
446
+ break image if OpenNebula.is_error?(image)
447
+ break vmtemplate if OpenNebula.is_error?(vmtemplate)
448
+
449
+ idx += 1
450
+
451
+ # Update exported hash with information
452
+ exported[app] = rc
453
+ exported[app][:names] = [obj_name]
454
+
455
+ # Add IDs to return object
456
+ images << image
457
+ templates << vmtemplate
458
+ end
459
+
460
+ if block_given? && !OpenNebula.is_error?(rc)
461
+ rc = yield(exported)
462
+ end
463
+
464
+ if OpenNebula.is_error?(rc)
465
+ rc_rbck = rollback_export(exported, xpath != '//DISK')
466
+
467
+ return rc_rbck if OpenNebula.is_error?(rc_rbck)
468
+ end
469
+
470
+ [rc, images, templates]
471
+ end
472
+
473
+ # Delete templates/images in case something went wrong
474
+ #
475
+ # @param exported [Hash] Exported apps information
476
+ # @param template [Boolean] True to delete VM Template
477
+ # False to delete images
478
+ #
479
+ # @return [nil | OpenNebula::Error]
480
+ def rollback_export(exported, is_template)
481
+ ret = ''
482
+
483
+ if is_template
484
+ obj_factory = lambda {|v|
485
+ id = v[:vmtemplate].first
486
+ [Template.new_with_id(id, @client),
487
+ "Error deleting template #{id}"]
488
+ }
489
+
490
+ delete_method = 'delete(true)'
491
+ else
492
+ obj_factory = lambda {|v|
493
+ id = v[:image].first
494
+ [Image.new_with_id(id, @client),
495
+ "Error deleting image #{id}"]
496
+ }
497
+
498
+ delete_method = 'delete'
499
+ end
500
+
501
+ exported.each do |_, v|
502
+ obj, err_msg = obj_factory.call(v)
503
+
504
+ next unless OpenNebula.is_error?(obj.send(delete_method))
505
+
506
+ ret << err_msg
507
+ end
508
+
509
+ if ret.empty?
510
+ nil
511
+ else
512
+ Error.new(ret) unless ret.empty?
513
+ end
514
+ end
515
+
516
+ end
517
+
518
+ super
519
+ end
520
+
521
+ end
522
+ # rubocop:enable Style/ClassAndModuleChildren