opennebula 6.10.3 → 6.99.85.pre

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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cloud/CloudClient.rb +3 -3
  3. data/lib/models/role.rb +349 -823
  4. data/lib/models/service.rb +156 -80
  5. data/lib/models/vmrole.rb +703 -0
  6. data/lib/models/vrrole.rb +284 -0
  7. data/lib/models.rb +3 -1
  8. data/lib/opennebula/acl.rb +1 -1
  9. data/lib/opennebula/acl_pool.rb +1 -1
  10. data/lib/opennebula/backupjob.rb +1 -1
  11. data/lib/opennebula/backupjob_pool.rb +1 -1
  12. data/lib/opennebula/client.rb +1 -1
  13. data/lib/opennebula/cluster.rb +45 -2
  14. data/lib/opennebula/cluster_pool.rb +1 -1
  15. data/lib/opennebula/datastore.rb +1 -1
  16. data/lib/opennebula/datastore_pool.rb +1 -1
  17. data/lib/opennebula/document.rb +1 -1
  18. data/lib/opennebula/document_json.rb +1 -1
  19. data/lib/opennebula/document_pool.rb +1 -1
  20. data/lib/opennebula/document_pool_json.rb +1 -1
  21. data/lib/opennebula/error.rb +1 -1
  22. data/lib/opennebula/flow/grammar.rb +1 -1
  23. data/lib/opennebula/flow/service_pool.rb +1 -1
  24. data/lib/opennebula/flow/service_template.rb +353 -97
  25. data/lib/opennebula/flow/service_template_ext.rb +3 -3
  26. data/lib/opennebula/flow/service_template_pool.rb +1 -1
  27. data/lib/opennebula/flow/validator.rb +458 -410
  28. data/lib/opennebula/flow.rb +1 -1
  29. data/lib/opennebula/group.rb +1 -1
  30. data/lib/opennebula/group_pool.rb +1 -1
  31. data/lib/opennebula/hook.rb +1 -1
  32. data/lib/opennebula/hook_log.rb +1 -1
  33. data/lib/opennebula/hook_pool.rb +1 -1
  34. data/lib/opennebula/host.rb +1 -60
  35. data/lib/opennebula/host_pool.rb +1 -1
  36. data/lib/opennebula/image.rb +1 -1
  37. data/lib/opennebula/image_pool.rb +1 -1
  38. data/lib/opennebula/ldap_auth.rb +1 -1
  39. data/lib/opennebula/ldap_auth_spec.rb +1 -1
  40. data/lib/opennebula/lockable_ext.rb +1 -1
  41. data/lib/opennebula/marketplace.rb +1 -1
  42. data/lib/opennebula/marketplace_pool.rb +1 -1
  43. data/lib/opennebula/marketplaceapp.rb +1 -1
  44. data/lib/opennebula/marketplaceapp_ext.rb +14 -211
  45. data/lib/opennebula/marketplaceapp_pool.rb +1 -1
  46. data/lib/opennebula/oneflow_client.rb +11 -9
  47. data/lib/opennebula/pool.rb +1 -1
  48. data/lib/opennebula/pool_element.rb +1 -1
  49. data/lib/opennebula/security_group.rb +1 -1
  50. data/lib/opennebula/security_group_pool.rb +1 -1
  51. data/lib/opennebula/server_cipher_auth.rb +1 -1
  52. data/lib/opennebula/server_x509_auth.rb +1 -1
  53. data/lib/opennebula/ssh_auth.rb +1 -1
  54. data/lib/opennebula/system.rb +1 -1
  55. data/lib/opennebula/template.rb +1 -1
  56. data/lib/opennebula/template_ext.rb +1 -1
  57. data/lib/opennebula/template_pool.rb +1 -1
  58. data/lib/opennebula/user.rb +1 -1
  59. data/lib/opennebula/user_pool.rb +1 -1
  60. data/lib/opennebula/utils.rb +2 -2
  61. data/lib/opennebula/vdc.rb +1 -1
  62. data/lib/opennebula/vdc_pool.rb +1 -1
  63. data/lib/opennebula/virtual_machine.rb +3 -12
  64. data/lib/opennebula/virtual_machine_ext.rb +2 -31
  65. data/lib/opennebula/virtual_machine_pool.rb +1 -1
  66. data/lib/opennebula/virtual_network.rb +1 -1
  67. data/lib/opennebula/virtual_network_pool.rb +1 -1
  68. data/lib/opennebula/virtual_router.rb +1 -1
  69. data/lib/opennebula/virtual_router_pool.rb +1 -1
  70. data/lib/opennebula/vm_group.rb +1 -1
  71. data/lib/opennebula/vm_group_pool.rb +1 -1
  72. data/lib/opennebula/vntemplate.rb +1 -1
  73. data/lib/opennebula/vntemplate_pool.rb +1 -1
  74. data/lib/opennebula/wait_ext.rb +1 -1
  75. data/lib/opennebula/x509_auth.rb +1 -1
  76. data/lib/opennebula/xml_element.rb +2 -2
  77. data/lib/opennebula/xml_pool.rb +1 -1
  78. data/lib/opennebula/xml_utils.rb +1 -1
  79. data/lib/opennebula/zone.rb +1 -1
  80. data/lib/opennebula/zone_pool.rb +1 -1
  81. data/lib/opennebula.rb +2 -2
  82. metadata +6 -67
  83. data/lib/ActionManager.rb +0 -280
  84. data/lib/CommandManager.rb +0 -328
  85. data/lib/DriverExecHelper.rb +0 -213
  86. data/lib/HostSyncManager.rb +0 -111
  87. data/lib/OpenNebulaDriver.rb +0 -223
  88. data/lib/VirtualMachineDriver.rb +0 -404
  89. data/lib/datacenter.rb +0 -1319
  90. data/lib/datastore.rb +0 -1049
  91. data/lib/distributed_firewall.rb +0 -293
  92. data/lib/file_helper.rb +0 -374
  93. data/lib/host.rb +0 -1518
  94. data/lib/logical_port.rb +0 -50
  95. data/lib/logical_switch.rb +0 -77
  96. data/lib/memoize.rb +0 -74
  97. data/lib/network.rb +0 -705
  98. data/lib/nsx_client.rb +0 -157
  99. data/lib/nsx_component.rb +0 -28
  100. data/lib/nsx_constants.rb +0 -162
  101. data/lib/nsx_driver.rb +0 -91
  102. data/lib/nsx_error.rb +0 -77
  103. data/lib/nsx_rule.rb +0 -206
  104. data/lib/nsxt_client.rb +0 -189
  105. data/lib/nsxt_dfw.rb +0 -196
  106. data/lib/nsxt_logical_port.rb +0 -94
  107. data/lib/nsxt_rule.rb +0 -188
  108. data/lib/nsxt_tz.rb +0 -38
  109. data/lib/nsxv_client.rb +0 -189
  110. data/lib/nsxv_dfw.rb +0 -202
  111. data/lib/nsxv_logical_port.rb +0 -107
  112. data/lib/nsxv_rule.rb +0 -172
  113. data/lib/nsxv_tz.rb +0 -41
  114. data/lib/opaque_network.rb +0 -134
  115. data/lib/rest_client.rb +0 -191
  116. data/lib/scripts_common.rb +0 -176
  117. data/lib/transport_zone.rb +0 -43
  118. data/lib/vcenter_driver.rb +0 -152
  119. data/lib/vcenter_importer.rb +0 -626
  120. data/lib/vi_client.rb +0 -273
  121. data/lib/vi_helper.rb +0 -328
  122. data/lib/virtual_machine.rb +0 -3574
  123. data/lib/virtual_wire.rb +0 -158
  124. data/lib/vm_device.rb +0 -80
  125. data/lib/vm_disk.rb +0 -202
  126. data/lib/vm_folder.rb +0 -69
  127. data/lib/vm_helper.rb +0 -30
  128. data/lib/vm_monitor.rb +0 -305
  129. data/lib/vm_nic.rb +0 -70
  130. data/lib/vm_template.rb +0 -2112
  131. data/lib/vmm_importer.rb +0 -165
data/lib/datastore.rb DELETED
@@ -1,1049 +0,0 @@
1
- # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2024, 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
- # Ruby 3.x+ deprecated URI.escape, however rbvmomi still relies on it
18
-
19
- if RUBY_VERSION.split('.')[0].to_i >= 3
20
- # Monkey patch the escape functionality
21
- module URI
22
-
23
- def self.escape(url)
24
- URI::Parser.new.escape url
25
- end
26
-
27
- end
28
- end
29
-
30
- ##############################################################################
31
- # Module VCenterDriver
32
- ##############################################################################
33
- module VCenterDriver
34
-
35
- require 'digest'
36
- require 'uri'
37
-
38
- ##########################################################################
39
- # Class DatastoreFolder
40
- ##########################################################################
41
- class DatastoreFolder
42
-
43
- attr_accessor :item, :items
44
-
45
- def initialize(item)
46
- @item = item
47
- @items = {}
48
- end
49
-
50
- ######################################################################
51
- # Builds a hash with Datastore-Ref / Datastore to be used as a cache
52
- # @return [Hash] in the form
53
- # { ds_ref [Symbol] => Datastore object }
54
- ######################################################################
55
- def fetch!
56
- VIClient.get_entities(@item, 'Datastore').each do |item|
57
- item_name = item._ref
58
- @items[item_name.to_sym] = Datastore.new(item)
59
- end
60
-
61
- VIClient.get_entities(@item, 'StoragePod').each do |sp|
62
- @items[sp._ref.to_sym] = StoragePod.new(sp)
63
- VIClient.get_entities(sp, 'Datastore').each do |item|
64
- item_name = item._ref
65
- @items[item_name.to_sym] = Datastore.new(item)
66
- end
67
- end
68
- @items
69
- end
70
-
71
- ######################################################################
72
- # Returns a Datastore or StoragePod. Uses the cache if available.
73
- # @param ref [Symbol] the vcenter ref
74
- # @return Datastore
75
- ######################################################################
76
- def get(ref)
77
- if !@items[ref.to_sym]
78
- if ref.start_with?('group-')
79
- rbvmomi_spod = RbVmomi::VIM::StoragePod
80
- .new(
81
- @item._connection,
82
- ref
83
- ) rescue nil
84
- @items[ref.to_sym] = StoragePod.new(rbvmomi_spod)
85
- else
86
- rbvmomi_ds = RbVmomi::VIM::Datastore
87
- .new(
88
- @item._connection,
89
- ref
90
- ) rescue nil
91
- @items[ref.to_sym] = Datastore.new(rbvmomi_ds)
92
- end
93
- end
94
- @items[ref.to_sym]
95
- end
96
-
97
- end
98
- # class DatastoreFolder
99
-
100
- ##########################################################################
101
- # Class Storage
102
- ##########################################################################
103
- class Storage
104
-
105
- attr_accessor :item
106
-
107
- include Memoize
108
-
109
- CURLBIN = 'curl'
110
-
111
- def self.new_from_ref(ref, vi_client)
112
- if ref.start_with?('group-')
113
- VCenterDriver::StoragePod.new_from_ref(ref, vi_client)
114
- else
115
- VCenterDriver::Datastore.new_from_ref(ref, vi_client)
116
- end
117
- end
118
-
119
- def self.get_image_import_template(params)
120
- disk = params[:disk]
121
- ipool = params[:ipool]
122
- _type = params[:_type]
123
- ds_id = params[:ds_id]
124
- opts = params[:opts]
125
- images = params[:images]
126
-
127
- VCenterDriver::VIHelper.check_opts(opts, [:persistent])
128
-
129
- ds_name = disk[:datastore].name
130
- image_path = disk[:path_wo_ds]
131
- image_type = disk[:type]
132
- image_prefix = disk[:prefix]
133
-
134
- image_name = nil
135
-
136
- one_image = {}
137
- one_image[:template] = ''
138
-
139
- # Get image name
140
- file_name = File.basename(image_path).gsub(/\.vmdk$/, '')
141
-
142
- # Check if the image has already been imported
143
- image = VIHelper
144
- .find_image_by(
145
- 'SOURCE',
146
- OpenNebula::ImagePool,
147
- image_path,
148
- ds_id,
149
- ipool
150
- )
151
-
152
- if image.nil?
153
- key = "#{file_name}#{ds_name}#{image_path}"
154
- byte = 0
155
- image_name = VCenterDriver::VIHelper
156
- .one_name(
157
- OpenNebula::ImagePool,
158
- file_name,
159
- key,
160
- ipool,
161
- byte
162
- )
163
- while images.include?(image_name)
164
- byte += 2
165
- image_name = VCenterDriver::VIHelper
166
- .one_name(
167
- OpenNebula::ImagePool,
168
- file_name,
169
- key,
170
- ipool,
171
- byte
172
- )
173
- end
174
-
175
- # Set template
176
- one_image[:template] << "NAME=\"#{image_name}\"\n"
177
- one_image[:template] << "PATH=\"vcenter://#{image_path}\"\n"
178
- one_image[:template] << "TYPE=\"#{image_type}\"\n"
179
- one_image[:template] << "PERSISTENT=\"#{opts[:persistent]}\"\n"
180
- unless CONFIG[:delete_images]
181
- one_image[:template] << "VCENTER_IMPORTED=\"YES\"\n"
182
- end
183
- one_image[:template] << "DEV_PREFIX=\"#{image_prefix}\"\n"
184
- else
185
- # Return the image XML if it already exists
186
- one_image[:one] = image
187
- end
188
-
189
- [one_image, image_name]
190
- end
191
-
192
- def self.get_one_image_ds_by_ref_and_dc(
193
- ref,
194
- dc_ref,
195
- vcenter_uuid,
196
- pool = nil
197
- )
198
- if pool.nil?
199
- pool = VCenterDriver::VIHelper
200
- .one_pool(
201
- OpenNebula::DatastorePool,
202
- false
203
- )
204
- if pool.respond_to?(:message)
205
- raise "Could not get \
206
- OpenNebula DatastorePool: #{pool.message}"
207
- end
208
- end
209
-
210
- pool.select do |e|
211
- e['TEMPLATE/TYPE'] == 'IMAGE_DS' &&
212
- e['TEMPLATE/VCENTER_DS_REF'] == ref &&
213
- e['TEMPLATE/VCENTER_DC_REF'] == dc_ref &&
214
- e['TEMPLATE/VCENTER_INSTANCE_ID'] == vcenter_uuid
215
- end.first rescue nil
216
- end
217
-
218
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk or an iso file
219
- def self.disk_or_iso?(device)
220
- is_disk = !device.class.ancestors.index(
221
- RbVmomi::VIM::VirtualDisk
222
- ).nil?
223
- is_iso = device
224
- .backing.is_a? RbVmomi::VIM::VirtualCdromIsoBackingInfo
225
- is_disk || is_iso
226
- end
227
-
228
- def monitor
229
- summary = self['summary']
230
-
231
- total_mb = (summary.capacity.to_i / 1024) / 1024
232
- free_mb = (summary.freeSpace.to_i / 1024) / 1024
233
- used_mb = total_mb - free_mb
234
-
235
- "USED_MB=#{used_mb}\nFREE_MB=#{free_mb} \nTOTAL_MB=#{total_mb}"
236
- end
237
-
238
- def self.exists_one_by_ref_dc_and_type?(
239
- ref,
240
- dc_ref,
241
- vcenter_uuid,
242
- type,
243
- pool = nil
244
- )
245
- if pool.nil?
246
- pool = VCenterDriver::VIHelper.one_pool(
247
- OpenNebula::DatastorePool,
248
- false
249
- )
250
- if pool.respond_to?(:message)
251
- raise "Could not get OpenNebula \
252
- DatastorePool: #{pool.message}"
253
- end
254
- end
255
- elements = pool.select do |e|
256
- e['TEMPLATE/TYPE'] == type &&
257
- e['TEMPLATE/VCENTER_DS_REF'] == ref &&
258
- e['TEMPLATE/VCENTER_DC_REF'] == dc_ref &&
259
- e['TEMPLATE/VCENTER_INSTANCE_ID'] == vcenter_uuid
260
- end
261
-
262
- elements.size == 1
263
- end
264
-
265
- def to_one(ds_hash, vcenter_uuid, dc_name, dc_ref)
266
- one = ''
267
- one << "DRIVER=\"vcenter\"\n"
268
- one << "NAME=\"#{ds_hash[:name]}\"\n"
269
- one << "TM_MAD=vcenter\n"
270
- one << "VCENTER_INSTANCE_ID=\"#{vcenter_uuid}\"\n"
271
- one << "VCENTER_DC_REF=\"#{dc_ref}\"\n"
272
- one << "VCENTER_DC_NAME=\"#{dc_name}\"\n"
273
- one << "VCENTER_DS_NAME=\"#{ds_hash[:simple_name]}\"\n"
274
- one << "VCENTER_DS_REF=\"#{self['_ref']}\"\n"
275
- one
276
- end
277
-
278
- def to_one_template(ds_hash, vcenter_uuid, dc_name, dc_ref, type)
279
- one_tmp = {
280
- :one => to_one(ds_hash, vcenter_uuid, dc_name, dc_ref)
281
- }
282
-
283
- if type == 'SYSTEM_DS'
284
- one_tmp[:one] << "TYPE=SYSTEM_DS\n"
285
- else
286
- one_tmp[:one] << "DS_MAD=vcenter\n"
287
- one_tmp[:one] << "TYPE=IMAGE_DS\n"
288
- end
289
-
290
- one_tmp
291
- end
292
-
293
- def create_virtual_disk(img_name, size, adapter_type, disk_type)
294
- leading_dirs = img_name.split('/')[0..-2]
295
- if !leading_dirs.empty?
296
- create_directory(leading_dirs.join('/'))
297
- end
298
-
299
- ds_name = self['name']
300
-
301
- vmdk_spec = RbVmomi::VIM::FileBackedVirtualDiskSpec(
302
- :adapterType => adapter_type,
303
- :capacityKb => size.to_i*1024,
304
- :diskType => disk_type
305
- )
306
-
307
- obtain_vdm.CreateVirtualDisk_Task(
308
- :datacenter => obtain_dc.item,
309
- :name => "[#{ds_name}] #{img_name}.vmdk",
310
- :spec => vmdk_spec
311
- ).wait_for_completion
312
-
313
- "#{img_name}.vmdk"
314
- end
315
-
316
- def create_directory(directory)
317
- ds_name = self['name']
318
-
319
- return if self.class == VCenterDriver::StoragePod
320
-
321
- directory_name = "[#{ds_name}] #{directory}"
322
-
323
- create_directory_params = {
324
- :name => directory_name,
325
- :datacenter => obtain_dc.item,
326
- :createParentDirectories => true
327
- }
328
-
329
- obtain_fm.MakeDirectory(create_directory_params) rescue nil
330
- end
331
-
332
- def obtain_fm
333
- self['_connection.serviceContent.fileManager']
334
- end
335
-
336
- def obtain_vdm
337
- self['_connection.serviceContent.virtualDiskManager']
338
- end
339
-
340
- def obtain_dc
341
- item = @item
342
-
343
- until item.instance_of? RbVmomi::VIM::Datacenter
344
- item = item.parent
345
- if item.nil?
346
- raise 'Could not find the parent Datacenter'
347
- end
348
- end
349
-
350
- Datacenter.new(item)
351
- end
352
-
353
- end
354
- # class Storage
355
-
356
- ########################################################################
357
- # Class StoragePod
358
- ########################################################################
359
- class StoragePod < Storage
360
-
361
- def initialize(item, _vi_client = nil)
362
- check_item(item, RbVmomi::VIM::StoragePod)
363
- @item = item
364
-
365
- super()
366
- end
367
-
368
- # This is never cached
369
- def self.new_from_ref(ref, vi_client)
370
- new(RbVmomi::VIM::StoragePod.new(vi_client.vim, ref), vi_client)
371
- end
372
-
373
- end
374
- # class StoragePod
375
-
376
- ##########################################################################
377
- # Class Datastore
378
- ##########################################################################
379
- class Datastore < Storage
380
-
381
- attr_accessor :one_item
382
-
383
- def initialize(item, vi_client = nil)
384
- check_item(item, RbVmomi::VIM::Datastore)
385
- @vi_client = vi_client
386
- @item = item
387
- @one_item = {}
388
-
389
- super()
390
- end
391
-
392
- def delete_virtual_disk(img_name)
393
- ds_name = self['name']
394
-
395
- begin
396
- obtain_vdm.DeleteVirtualDisk_Task(
397
- :name => "[#{ds_name}] #{img_name}",
398
- :datacenter => obtain_dc.item
399
- ).wait_for_completion
400
- rescue StandardError => e
401
- # Ignore if file not found
402
- if !e.message.start_with?('ManagedObjectNotFound') &&
403
- !e.message.start_with?('FileNotFound')
404
- raise e
405
- end
406
- end
407
- end
408
-
409
- def delete_file(img_name)
410
- ds_name = self['name']
411
-
412
- begin
413
- obtain_fm.DeleteDatastoreFile_Task(
414
- :name => "[#{ds_name}] #{img_name}",
415
- :datacenter => obtain_dc.item
416
- ).wait_for_completion
417
- rescue StandardError => e
418
- # Ignore if file not found
419
- if !e.message.start_with?('ManagedObjectNotFound') &&
420
- !e.message.start_with?('FileNotFound')
421
- raise e
422
- end
423
- end
424
- end
425
-
426
- # Copy a VirtualDisk
427
- def copy_virtual_disk(src_path, target_ds, target_path, new_size = nil)
428
- source_ds_name = self['name']
429
- target_ds_name = target_ds['name']
430
-
431
- leading_dirs = target_path.split('/')[0..-2]
432
- if !leading_dirs.empty?
433
- if source_ds_name == target_ds_name
434
- create_directory(leading_dirs.join('/'))
435
- else
436
- target_ds.create_directory(leading_dirs.join('/'))
437
- end
438
- end
439
-
440
- copy_params = {
441
- :sourceName => "[#{source_ds_name}] #{src_path}",
442
- :sourceDatacenter => obtain_dc.item
443
- }
444
-
445
- if File.extname(src_path) == '.vmdk'
446
- copy_params[:destName] = "[#{target_ds_name}] #{target_path}"
447
- obtain_vdm.CopyVirtualDisk_Task(copy_params).wait_for_completion
448
-
449
- if new_size
450
- resize_spec = {
451
- :name => "[#{target_ds_name}] #{target_path}",
452
- :datacenter => target_ds.obtain_dc.item,
453
- :newCapacityKb => new_size,
454
- :eagerZero => false
455
- }
456
-
457
- obtain_vdm.ExtendVirtualDisk_Task(
458
- resize_spec
459
- ).wait_for_completion
460
- end
461
- else
462
- copy_params[:destinationName] =
463
- "[#{target_ds_name}] #{target_path}"
464
- obtain_fm.CopyDatastoreFile_Task(
465
- copy_params
466
- ).wait_for_completion
467
- end
468
-
469
- target_path
470
- end
471
-
472
- def move_virtual_disk(disk, dest_path, dest_dsid, vi_client = nil)
473
- vi_client ||= @vi_client
474
-
475
- target_ds = VCenterDriver::VIHelper.one_item(
476
- OpenNebula::Datastore,
477
- dest_dsid,
478
- false
479
- )
480
- target_ds_ref = target_ds['TEMPLATE/VCENTER_DS_REF']
481
- target_ds_vc = VCenterDriver::Datastore
482
- .new_from_ref(
483
- target_ds_ref,
484
- vi_client
485
- )
486
- dest_name = target_ds_vc['name']
487
-
488
- target_ds_vc.create_directory(File.dirname(dest_path))
489
-
490
- dpath_ds = "[#{dest_name}] #{dest_path}"
491
- orig_path = "[#{self['name']}] #{disk.path}"
492
-
493
- move_params = {
494
- :sourceName => orig_path,
495
- :sourceDatacenter => obtain_dc.item,
496
- :destName => dpath_ds,
497
- :force => true
498
- }
499
-
500
- obtain_vdm.MoveVirtualDisk_Task(move_params).wait_for_completion
501
- end
502
-
503
- def rm_directory(directory)
504
- ds_name = self['name']
505
-
506
- rm_directory_params = {
507
- :name => "[#{ds_name}] #{directory}",
508
- :datacenter => obtain_dc.item
509
- }
510
-
511
- obtain_fm.DeleteDatastoreFile_Task(
512
- rm_directory_params
513
- ).wait_for_completion
514
- end
515
-
516
- def dir_empty?(path)
517
- ds_name = self['name']
518
-
519
- spec = RbVmomi::VIM::HostDatastoreBrowserSearchSpec.new
520
-
521
- search_params = {
522
- 'datastorePath' => "[#{ds_name}] #{path}",
523
- 'searchSpec' => spec
524
- }
525
-
526
- begin
527
- search_task = self['browser']
528
- .SearchDatastoreSubFolders_Task(search_params)
529
- search_task.wait_for_completion
530
- !search_task.info.result.nil? &&
531
- search_task.info.result.length == 1 &&
532
- search_task.info.result.first.file.empty?
533
- rescue StandardError
534
- false
535
- end
536
- end
537
-
538
- def upload_file(source_path, target_path)
539
- @item.upload(target_path, source_path)
540
- end
541
-
542
- def download_file(source_path, target_path)
543
- @item.download(source_path, target_path)
544
- end
545
-
546
- # Get file size for image handling
547
- def stat(img_str)
548
- ds_name = self['name']
549
- img_path = File.dirname img_str
550
- img_name = File.basename img_str
551
-
552
- # Create Search Spec
553
- search_params = get_search_params(ds_name, img_path, img_name)
554
-
555
- # Perform search task and return results
556
- begin
557
- search_task = self['browser']
558
- .SearchDatastoreSubFolders_Task(search_params)
559
-
560
- search_task.wait_for_completion
561
-
562
- # Try to get vmdk capacity as seen by VM
563
- size = search_task
564
- .info.result[0].file[0].capacityKb / 1024 rescue nil
565
-
566
- # Try to get file size
567
- size ||= search_task
568
- .info
569
- .result[0].file[0].fileSize / 1024 / 1024 rescue nil
570
-
571
- raise 'Could not get file size or capacity' if size.nil?
572
-
573
- size
574
- rescue StandardError => e
575
- message = "Could not find file. Reason: \"#{e.message}\"."
576
- if VCenterDriver::CONFIG[:debug_information]
577
- message += ' ' + e.backtrace.to_s
578
- end
579
- raise message
580
- end
581
- end
582
-
583
- def get_search_params(ds_name, img_path = nil, img_name = nil)
584
- spec = RbVmomi::VIM::HostDatastoreBrowserSearchSpec.new
585
-
586
- vmdisk_query = RbVmomi::VIM::VmDiskFileQuery.new
587
- vmdisk_query.details = RbVmomi::VIM::VmDiskFileQueryFlags(
588
- :diskType => true,
589
- :capacityKb => true,
590
- :hardwareVersion => true,
591
- :controllerType => true
592
- )
593
-
594
- spec.query = [vmdisk_query,
595
- RbVmomi::VIM::IsoImageFileQuery.new]
596
- spec.details = RbVmomi::VIM::FileQueryFlags(
597
- :fileOwner => true,
598
- :fileSize => true,
599
- :fileType => true,
600
- :modification => true
601
- )
602
-
603
- if img_name.nil?
604
- spec.matchPattern = []
605
- else
606
- spec.matchPattern = [img_name]
607
- end
608
-
609
- datastore_path = "[#{ds_name}]"
610
- datastore_path << " #{img_path}" unless img_path.nil?
611
-
612
- { 'datastorePath' => datastore_path,
613
- 'searchSpec' => spec }
614
- end
615
-
616
- def dc_path
617
- dc = obtain_dc
618
- p = dc.item.parent
619
- path = [dc.item.name]
620
- while p.instance_of? RbVmomi::VIM::Folder
621
- path.unshift(p.name)
622
- p = p.parent
623
- end
624
- path.delete_at(0) # The first folder is the root "Datacenters"
625
- path.join('/')
626
- end
627
-
628
- def generate_file_url(path)
629
- if self['_connection.http.use_ssl?']
630
- protocol = 'https://'
631
- else
632
- protocol = 'http://'
633
- end
634
- hostname = self['_connection.http.address']
635
- port = self['_connection.http.port']
636
- dcpath = dc_path
637
- url_path = "folder/#{path}?dcPath=#{dcpath}&dsName=#{self['name']}"
638
-
639
- # This creates the vcenter file URL
640
- # for uploading or downloading files
641
- # e.g:
642
- url = "#{protocol}#{hostname}:#{port}/#{url_path}"
643
- URI.escape(url) # rubocop:disable Lint/UriEscapeUnescape
644
- end
645
-
646
- def download_to_stdout(remote_path)
647
- url = generate_file_url(remote_path)
648
- pid = spawn(CURLBIN,
649
- '-k', '--noproxy', '*', '-f',
650
- '-b', self['_connection.cookie'],
651
- url)
652
-
653
- Process.waitpid(pid, 0)
654
- raise 'download failed' unless $?.success? # rubocop:disable Style/SpecialGlobalVars
655
- end
656
-
657
- def descriptor?(remote_path)
658
- url = generate_file_url(remote_path)
659
-
660
- rout, wout = IO.pipe
661
- pid = spawn(CURLBIN,
662
- '-I', '-k', '--noproxy', '*', '-f',
663
- '-b', self['_connection.cookie'],
664
- url,
665
- :out => wout,
666
- :err => '/dev/null')
667
-
668
- Process.waitpid(pid, 0)
669
- raise 'read image header failed' unless $?.success? # rubocop:disable Style/SpecialGlobalVars
670
-
671
- wout.close
672
- size = rout.readlines.select do |l|
673
- l.downcase.start_with?('content-length')
674
- end[0].downcase.sub('content-length: ', '')
675
- rout.close
676
- size.chomp.to_i < 4096 # If <4k, then is a descriptor
677
- end
678
-
679
- def get_text_file(remote_path)
680
- url = generate_file_url(remote_path)
681
-
682
- rout, wout = IO.pipe
683
- pid = spawn CURLBIN, '-k', '--noproxy', '*', '-f',
684
- '-b', self['_connection.cookie'],
685
- url,
686
- :out => wout,
687
- :err => '/dev/null'
688
-
689
- Process.waitpid(pid, 0)
690
- raise 'get text file failed' unless $?.success? # rubocop:disable Style/SpecialGlobalVars
691
-
692
- wout.close
693
- output = rout.readlines
694
- rout.close
695
- output
696
- end
697
-
698
- def all_images
699
- images = {}
700
- imid = -1
701
- ds_id = nil
702
- ds_name = self['name']
703
-
704
- # We need OpenNebula Images and Datastores pools
705
- ipool = VCenterDriver::VIHelper
706
- .one_pool(OpenNebula::ImagePool, false)
707
- if ipool.respond_to?(:message)
708
- raise "Could not get OpenNebula ImagePool: #{pool.message}"
709
- end
710
-
711
- dpool = VCenterDriver::VIHelper
712
- .one_pool(OpenNebula::DatastorePool, false)
713
- if dpool.respond_to?(:message)
714
- raise "Could not get OpenNebula DatastorePool: #{pool.message}"
715
- end
716
-
717
- ds_id = @one_item['ID']
718
-
719
- begin
720
- # Create Search Spec
721
- search_params = get_search_params(ds_name)
722
-
723
- # Perform search task and return results
724
- search_task = self['browser']
725
- .SearchDatastoreSubFolders_Task(search_params)
726
- search_task.wait_for_completion
727
-
728
- # Loop through search results
729
- search_task.info.result.each do |result|
730
- # Remove [datastore] from file path
731
- folderpath = ''
732
- size = result.folderPath.size
733
- if result.folderPath[-1] != ']'
734
- if result.folderPath[-1] != '/'
735
- result.folderPath[size] = '/'
736
- end
737
- folderpath = result
738
- .folderPath.sub(/^\[#{ds_name}\] /, '')
739
- end
740
-
741
- # Loop through images in result.file
742
- result.file.each do |image|
743
- image_path = ''
744
-
745
- # Skip not relevant files
746
- next unless ['FloppyImageFileInfo',
747
- 'IsoImageFileInfo',
748
- 'VmDiskFileInfo'].include? image.class.to_s
749
-
750
- # Get image path and name
751
- image_path << folderpath << image.path
752
- image_name = File.basename(image.path)
753
- .reverse.sub('kdmv.', '').reverse
754
-
755
- # Get image's type
756
- if image.class.to_s == 'VmDiskFileInfo'
757
- image_type = 'OS'
758
- else
759
- image_type = 'CDROM'
760
- end
761
-
762
- # Get image's size
763
- image_size = image.capacityKb / 1024 rescue nil
764
- image_size ||= image.fileSize / 1024 / 1024 rescue nil
765
-
766
- # Assign image prefix if known or assign default prefix
767
- controller = image.controllerType rescue nil
768
- if controller
769
- if controller == 'VirtualIDEController'
770
- disk_prefix = 'hd'
771
- else
772
- disk_prefix = 'sd'
773
- end
774
- else
775
- # Get default value for disks that
776
- # are not attached to any controller
777
- disk_prefix = VCenterDriver::VIHelper
778
- .get_default(
779
- 'IMAGE/TEMPLATE/DEV_PREFIX'
780
- )
781
- end
782
-
783
- # Generate a crypto hash
784
- # this hash is used to avoid name collisions
785
- key = "#{image_name}#{ds_name}#{image_path}"
786
- import_name = VCenterDriver::VIHelper
787
- .one_name(
788
- OpenNebula::ImagePool,
789
- image_name,
790
- key,
791
- ipool
792
- )
793
-
794
- # Set template
795
- one_image = "NAME=\"#{import_name}\"\n"
796
- one_image << "PATH=\"vcenter://#{image_path}\"\n"
797
- one_image << "PERSISTENT=\"NO\"\n"
798
- one_image << "TYPE=\"#{image_type}\"\n"
799
- unless CONFIG[:delete_images]
800
- one_image << "VCENTER_IMPORTED=\"YES\"\n"
801
- end
802
- one_image << "DEV_PREFIX=\"#{disk_prefix}\"\n"
803
-
804
- # Check image hasn't already been imported
805
- image_found = VCenterDriver::VIHelper
806
- .find_image_by(
807
- 'SOURCE',
808
- OpenNebula::ImagePool,
809
- image_path,
810
- ds_id,
811
- ipool
812
- )
813
-
814
- next if image_found
815
-
816
- # Add template to image array
817
- images[import_name] = {
818
- :import_id => imid+=1,
819
- :name => import_name,
820
- :ref => import_name,
821
- :path => image_path,
822
- :size => image_size.to_s,
823
- :type => image.class.to_s,
824
- :dsid => ds_id,
825
- :one => one_image
826
- }
827
- end
828
- end
829
- rescue StandardError => e
830
- raise "Could not find images. \
831
- Reason: #{e.message}/#{e.backtrace}"
832
- end
833
- vname = @vi_client.vc_name || ''
834
-
835
- { vname => images }
836
- end
837
-
838
- # This is never cached
839
- def self.new_from_ref(ref, vi_client)
840
- new(RbVmomi::VIM::Datastore.new(vi_client.vim, ref), vi_client)
841
- end
842
-
843
- # detach disk from vCenter vm if possible, destroy the disk on FS
844
- def self.detach_and_destroy(disk, vm, disk_id, prev_ds_ref, vi_client)
845
- # it's not a CDROM (CLONE=NO)
846
- is_cd = !(disk['CLONE'].nil? || disk['CLONE'] == 'YES')
847
-
848
- begin
849
- # Detach disk if possible (VM is reconfigured)
850
- # and gather vCenter info
851
- # Needed for poweroff machines too
852
- ds_ref, img_path = vm.detach_disk(disk)
853
-
854
- return if is_cd
855
-
856
- # Disk could't be detached, use OpenNebula info
857
- if !(ds_ref && img_path && !img_path.empty?)
858
- img_path = vm.disk_real_path(disk, disk_id)
859
- ds_ref = prev_ds_ref
860
- end
861
-
862
- # If disk was already detached we have no way to remove it
863
- ds = VCenterDriver::Datastore.new_from_ref(ds_ref, vi_client)
864
-
865
- search_params = ds.get_search_params(ds['name'],
866
- File.dirname(img_path),
867
- File.basename(img_path))
868
-
869
- # Perform search task and return results
870
- search_task = ds['browser']
871
- .SearchDatastoreSubFolders_Task(search_params)
872
- search_task.wait_for_completion
873
-
874
- ds.delete_virtual_disk(img_path)
875
- img_dir = File.dirname(img_path)
876
- ds.rm_directory(img_dir) if ds.dir_empty?(img_dir)
877
- rescue StandardError => e
878
- if !e.message.start_with?('FileNotFound')
879
- raise e.message # Ignore FileNotFound
880
- end
881
- end
882
- end
883
-
884
- end
885
- # class Datastore
886
-
887
- ##########################################################################
888
- # Class DsImporter
889
- ##########################################################################
890
- class DsImporter < VCenterDriver::VcImporter
891
-
892
- def initialize(one_client, vi_client)
893
- super(one_client, vi_client)
894
- @one_class = OpenNebula::Datastore
895
- end
896
-
897
- def get_list(args = {})
898
- dc_folder = VCenterDriver::DatacenterFolder.new(@vi_client)
899
-
900
- # one pool creation
901
- dpool = VCenterDriver::VIHelper
902
- .one_pool(
903
- OpenNebula::DatastorePool,
904
- false
905
- )
906
- if dpool.respond_to?(:message)
907
- raise "Could not get OpenNebula DatastorePool: #{dpool.message}"
908
- end
909
-
910
- # OpenNebula's HostPool
911
- hpool = VCenterDriver::VIHelper
912
- .one_pool(
913
- OpenNebula::HostPool,
914
- false
915
- )
916
- if hpool.respond_to?(:message)
917
- raise "Could not get OpenNebula HostPool: #{hpool.message}"
918
- end
919
-
920
- rs = dc_folder
921
- .get_unimported_datastores(
922
- dpool,
923
- @vi_client.vc_name,
924
- hpool,
925
- args
926
- )
927
- @list = rs
928
- end
929
-
930
- def add_cluster(cid, eid)
931
- one_cluster = @info[:clusters][cid]
932
- raise 'no cluster defined' unless one_cluster
933
-
934
- one_cluster.adddatastore(eid)
935
- end
936
-
937
- def remove_default(id)
938
- cid = 0
939
- @info[:clusters][cid] ||= VCenterDriver::VIHelper
940
- .one_item(
941
- OpenNebula::Cluster,
942
- cid.to_s,
943
- false
944
- )
945
- @info[:clusters][cid].deldatastore(id.to_i)
946
- end
947
-
948
- def import(selected)
949
- inner = lambda {|object, auth|
950
- one = ''
951
- one << "VCENTER_HOST=\"#{auth[:host]}\"\n"
952
-
953
- object.update(one, true)
954
- }
955
-
956
- opts = @info[selected[:ref]][:opts]
957
-
958
- # Datastore info comes in a pair (SYS, IMG)
959
- pair = selected[:ds]
960
- clusters = selected[:cluster]
961
- if opts && opts['selected_clusters']
962
- clusters = opts['selected_clusters'].each.map(&:to_i)
963
- end
964
-
965
- name = VCenterDriver::VcImporter.sanitize(
966
- selected[:simple_name]
967
- )
968
-
969
- res = { :id => [], :name => name }
970
- @info[:rollback] = []
971
- pair.each do |ds|
972
- create(ds[:one]) do |one_object, id|
973
- res[:id] << id
974
-
975
- add_clusters(id, clusters)
976
-
977
- inner.call(
978
- one_object,
979
- @vi_client.host_credentials(
980
- @one_client
981
- )
982
- )
983
- end
984
- end
985
-
986
- res
987
- end
988
-
989
- end
990
-
991
- ##########################################################################
992
- # Class ImageImporter
993
- ##########################################################################
994
- class ImageImporter < VCenterDriver::VcImporter
995
-
996
- def initialize(one_client, vi_client)
997
- super(one_client, vi_client)
998
- @one_class = OpenNebula::Image
999
- end
1000
-
1001
- def get_list(args = {})
1002
- ds_ref = args[:datastore][:ds_ref]
1003
- one_ds = args[:datastore][:one_item]
1004
-
1005
- unless ds_ref
1006
- raise "can't retrieve ref info from openNebula datastore"
1007
- end
1008
-
1009
- datastore = VCenterDriver::Datastore
1010
- .new_from_ref(ds_ref, @vi_client)
1011
-
1012
- ds = datastore.tap do |spawn|
1013
- spawn.one_item = one_ds
1014
- end
1015
-
1016
- vc_uuid = @vi_client.vim.serviceContent.about.instanceUuid
1017
- one_ds_instance_id = one_ds['TEMPLATE/VCENTER_INSTANCE_ID']
1018
-
1019
- if one_ds_instance_id != vc_uuid
1020
- raise 'Datastore is not in the same vCenter \
1021
- instance provided in credentials'
1022
- end
1023
-
1024
- @list = ds.all_images
1025
- end
1026
-
1027
- def import(selected)
1028
- resource = VCenterDriver::VIHelper.new_one_item(@one_class)
1029
- message = 'Error creating the OpenNebula resource'
1030
- info = selected[:one]
1031
- dsid = selected[:dsid].to_i
1032
- name = VCenterDriver::VcImporter.sanitize(
1033
- selected[:name]
1034
- )
1035
-
1036
- rc = resource.allocate(info, dsid, false)
1037
- VCenterDriver::VIHelper.check_error(rc, message)
1038
-
1039
- resource.info
1040
- id = resource['ID']
1041
- @rollback << Raction.new(resource, :delete)
1042
-
1043
- { :id => [id], :name => name }
1044
- end
1045
-
1046
- end
1047
-
1048
- end
1049
- # module VCenterDriver