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/vm_template.rb DELETED
@@ -1,2112 +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
- require 'ipaddr'
17
-
18
- ##############################################################################
19
- # Module VCenterDriver
20
- ##############################################################################
21
- module VCenterDriver
22
-
23
- ##########################################################################
24
- # Class Template
25
- ##########################################################################
26
- class Template
27
-
28
- attr_accessor :item
29
-
30
- include Memoize
31
-
32
- def initialize(item = nil, vi_client = nil)
33
- @item = item
34
- check_item(@item, nil) if @item
35
- @vi_client = vi_client
36
- @locking = true
37
- end
38
-
39
- # Locking function. Similar to flock
40
- def lock
41
- return unless @locking
42
-
43
- @locking_file = File.open('/var/tmp/vcenter-importer-lock', 'w')
44
- @locking_file.flock(File::LOCK_EX)
45
- end
46
-
47
- # Unlock driver execution mutex
48
- def unlock
49
- return unless @locking
50
-
51
- @locking_file.close
52
-
53
- return unless File.exist?('/var/tmp/vcenter-importer-lock')
54
-
55
- File.delete('/var/tmp/vcenter-importer-lock')
56
- end
57
-
58
- def vm?
59
- self.class == VCenterDriver::VirtualMachine
60
- end
61
-
62
- def online?
63
- raise 'vcenter item not found!' unless @item
64
-
65
- !@item['guest.net'].empty?
66
- end
67
-
68
- def datacenter
69
- item = @item
70
-
71
- trace = []
72
- while item && !item.instance_of?(RbVmomi::VIM::Datacenter)
73
- rp = item.resourcePool rescue nil
74
- if rp && rp.instance_of?(RbVmomi::VIM::VirtualApp)
75
- trace << 'rp:' + item.to_s
76
- item = rp.parent rescue nil
77
- else
78
- trace << item.to_s
79
- item = item.parent rescue nil
80
- end
81
- end
82
-
83
- if item.nil?
84
- trace = '[' + trace.join(', ') + ']'
85
- raise "Could not find the parent Datacenter. Trace: #{trace}"
86
- end
87
-
88
- Datacenter.new(item)
89
- end
90
-
91
- def delete_template
92
- @item.Destroy_Task.wait_for_completion
93
- end
94
-
95
- def vcenter_instance_uuid
96
- @vi_client.vim.serviceContent.about.instanceUuid rescue nil
97
- end
98
-
99
- def save_as_linked_clones(name)
100
- error = nil
101
-
102
- disks = @item.config.hardware.device.grep(
103
- RbVmomi::VIM::VirtualMachine
104
- )
105
- disks.select {|x| x.backing.parent.nil? }.each do |disk|
106
- spec = {
107
- :deviceChange => [
108
- {
109
- :operation => :remove,
110
- :device => disk
111
- },
112
- {
113
- :operation => :add,
114
- :fileOperation => :create,
115
- :device => disk.dup.tap do |x|
116
- x.backing = x.backing.dup
117
- x.backing.fileName =
118
- "[#{disk.backing.datastore.name}]"
119
- x.backing.parent = disk.backing
120
- end
121
- }
122
- ]
123
- }
124
- @item.ReconfigVM_Task(
125
- :spec => spec
126
- ).wait_for_completion
127
- end
128
-
129
- relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(
130
- :diskMoveType => :moveChildMostDiskBacking
131
- )
132
-
133
- spec = RbVmomi::VIM.VirtualMachineCloneSpec(
134
- :location => relocateSpec,
135
- :powerOn => false,
136
- :template => true
137
- )
138
-
139
- new_template = @item.CloneVM_Task(
140
- :folder => @item.parent,
141
- :name => name,
142
- :spec => spec
143
- ).wait_for_completion
144
-
145
- new_vm_template_ref = new_template._ref
146
-
147
- one_client = OpenNebula::Client.new
148
- importer = VCenterDriver::VmImporter.new(
149
- one_client,
150
- @vi_client
151
- )
152
-
153
- importer.retrieve_resources({})
154
- importer.get_indexes(new_vm_template_ref)
155
-
156
- importer.process_import(
157
- new_vm_template_ref,
158
- {
159
- new_vm_template_ref.to_s => {
160
- :type => 'default',
161
- :linked_clone => '1',
162
- :copy => '0',
163
- :name => '',
164
- :folder => ''
165
- }
166
- }
167
- )
168
-
169
- begin
170
- importer.output[:success][0][:id][0]
171
- rescue StandardError => e
172
- error = 'Creating linked clone VM Template' \
173
- " failed due to \"#{e.message}\".\n"
174
-
175
- if VCenterDriver::CONFIG[:debug_information]
176
- error += " #{e.backtrace}\n"
177
- end
178
- end
179
-
180
- [error, new_vm_template_ref]
181
- end
182
-
183
- def create_template_copy(template_name)
184
- error = nil
185
- template_ref = nil
186
-
187
- template_name = "one-#{self['name']}" if template_name.empty?
188
-
189
- relocate_spec_params = {}
190
- relocate_spec_params[:pool] = resource_pool
191
- relocate_spec =
192
- RbVmomi::VIM
193
- .VirtualMachineRelocateSpec(
194
- relocate_spec_params
195
- )
196
-
197
- clone_spec =
198
- RbVmomi::VIM
199
- .VirtualMachineCloneSpec(
200
- {
201
- :location => relocate_spec,
202
- :powerOn => false,
203
- :template => false
204
- }
205
- )
206
-
207
- begin
208
- template =
209
- @item
210
- .CloneVM_Task(
211
- :folder => @item.parent,
212
- :name => template_name,
213
- :spec => clone_spec
214
- ).wait_for_completion
215
- template_ref = template._ref
216
- rescue StandardError => e
217
- if !e.message.start_with?('DuplicateName')
218
- error = 'Could not create the template'\
219
- " clone. Reason: #{e.message}"
220
- return error, nil
221
- end
222
-
223
- dc = datacenter
224
- vm_folder = dc.vm_folder
225
- vm_folder.fetch!
226
- vm = vm_folder.items
227
- .select {|_k, v| v.item.name == template_name }
228
- .values.first.item rescue nil
229
-
230
- if vm
231
- begin
232
- vm.Destroy_Task.wait_for_completion
233
- template =
234
- @item
235
- .CloneVM_Task(
236
- :folder => @item.parent,
237
- :name => template_name,
238
- :spec => clone_spec
239
- ).wait_for_completion
240
- template_ref = template._ref
241
- rescue StandardError
242
- error = 'Could not delete the existing '\
243
- 'template, please remove it manually'\
244
- " from vCenter. Reason: #{e.message}"
245
- end
246
- else
247
- error = 'Could not create the template '\
248
- "clone. Reason: #{e.message}"
249
- end
250
- end
251
-
252
- [error, template_ref]
253
- end
254
-
255
- # Linked Clone over existing template
256
- def create_delta_disks
257
- begin
258
- disks =
259
- @item['config.hardware.device']
260
- .grep(RbVmomi::VIM::VirtualDisk)
261
- disk_without_snapshots = disks.select do |x|
262
- x.backing.parent.nil?
263
- end
264
- rescue StandardError
265
- error = 'Cannot extract existing disks on template.'
266
- use_linked_clones = false
267
- return error, use_linked_clones
268
- end
269
-
270
- if !disk_without_snapshots.empty?
271
-
272
- begin
273
- if self['config.template']
274
- @item.MarkAsVirtualMachine(
275
- :pool => resource_pool,
276
- :host => self['runtime.host']
277
- )
278
- end
279
- rescue StandardError => e
280
- @item.MarkAsTemplate()
281
- error = 'Cannot mark the template as a VirtualMachine. '\
282
- 'Not using linked clones. '\
283
- "Reason: #{e.message}/#{e.backtrace}"
284
- use_linked_clones = false
285
- return error, use_linked_clones
286
- end
287
-
288
- begin
289
- spec = {}
290
- spec[:deviceChange] = []
291
-
292
- disk_without_snapshots.each do |disk|
293
- remove_disk_spec =
294
- {
295
- :operation => :remove,
296
- :device => disk
297
- }
298
- spec[:deviceChange] << remove_disk_spec
299
-
300
- add_disk_spec =
301
- {
302
- :operation => :add,
303
- :fileOperation => :create,
304
- :device => disk.dup.tap do |x|
305
- x.backing =
306
- x.backing.dup
307
- x.backing.fileName =
308
- "[#{disk.backing.datastore.name}]"
309
- x.backing.parent =
310
- disk.backing
311
- end
312
- }
313
- spec[:deviceChange] << add_disk_spec
314
- end
315
-
316
- @item
317
- .ReconfigVM_Task(
318
- :spec => spec
319
- ).wait_for_completion unless spec[:deviceChange].empty?
320
- rescue StandardError => e
321
- error = 'Cannot create the delta disks on top '\
322
- "of the template. Reason: #{e.message}."
323
-
324
- if VCenterDriver::CONFIG[:debug_information]
325
- error += "\n\n#{e.backtrace}"
326
- end
327
-
328
- use_linked_clones = false
329
- return error, use_linked_clones
330
- end
331
-
332
- begin
333
- @item.MarkAsTemplate()
334
- rescue StandardError => e
335
- error = 'Cannot mark the VirtualMachine as '\
336
- 'a template. Not using linked clones.' \
337
- " Reason: #{e.message}."
338
-
339
- if VCenterDriver::CONFIG[:debug_information]
340
- error += "\n\n#{e.backtrace}"
341
- end
342
-
343
- use_linked_clones = false
344
- return error, use_linked_clones
345
- end
346
- end
347
-
348
- error = nil
349
- use_linked_clones = true
350
-
351
- [error, use_linked_clones]
352
- end
353
-
354
- ########################################################################
355
- # Import vcenter disks
356
- # @param type [object] contains the type of the object(:object) and
357
- # identifier(:id)
358
- # @return error, template_disks
359
- ########################################################################
360
- def import_vcenter_disks(vc_uuid, dpool, ipool, type)
361
- disk_info = ''
362
- error = ''
363
- images = []
364
-
365
- begin
366
- # Lock import operation, to avoid concurrent creation of images
367
- lock
368
-
369
- dc = datacenter
370
- dc_ref = dc.item._ref
371
-
372
- # Get disks and info required
373
- vc_disks = vcenter_disks_get
374
- vc_disks.sort_by! {|d| d[:device].unitNumber }
375
-
376
- # Track allocated images
377
- allocated_images = []
378
-
379
- vc_disks.each do |disk|
380
- ds_ref = nil
381
- begin
382
- ds_ref = disk[:datastore]._ref
383
- rescue StandardError
384
- raise "The ISO #{disk[:path_wo_ds].name} cannot "\
385
- 'be found because the datastore was '\
386
- 'removed or deleted'
387
- end
388
- datastore_found =
389
- VCenterDriver::Storage
390
- .get_one_image_ds_by_ref_and_dc(
391
- ds_ref,
392
- dc_ref,
393
- vc_uuid,
394
- dpool
395
- )
396
-
397
- if datastore_found.nil?
398
- error = "\n ERROR: datastore "\
399
- "#{disk[:datastore].name}: "\
400
- 'has to be imported first as'\
401
- " an image datastore!\n"
402
-
403
- # Rollback delete disk images
404
- allocated_images.each do |i|
405
- i.delete
406
- end
407
-
408
- break
409
- end
410
-
411
- # Read configuration for imported images, taking
412
- # into account if we are importing a VM Tempalte
413
- # or a Wild VM
414
- image_persistency = nil
415
- if vm?
416
- image_persistency = :wild_vm_persistent_images
417
- else
418
- image_persistency = :vm_template_persistent_images
419
- end
420
-
421
- image_persistency = VCenterDriver::CONFIG[image_persistency]
422
-
423
- params = {
424
- :disk => disk,
425
- :ipool => ipool,
426
- :_type => type,
427
- :ds_id => datastore_found['ID'],
428
- :opts => {
429
- :persistent => image_persistency ? 'YES':'NO'
430
- },
431
- :images => images
432
- }
433
-
434
- image_import, image_name =
435
- VCenterDriver::Datastore
436
- .get_image_import_template(
437
- params
438
- )
439
- # Image is already in the datastore
440
- if image_import[:one]
441
- # This is the disk info
442
- disk_tmp = ''
443
- disk_tmp << "DISK=[\n"
444
- disk_tmp <<
445
- "IMAGE_ID=\"#{image_import[:one]['ID']}\",\n"
446
- disk_tmp << "OPENNEBULA_MANAGED=\"NO\"\n"
447
- disk_tmp << "]\n"
448
- disk_info << disk_tmp
449
-
450
- elsif !image_import[:template].empty?
451
-
452
- # Then the image is created as it's not in the datastore
453
- one_i =
454
- VCenterDriver::VIHelper
455
- .new_one_item(
456
- OpenNebula::Image
457
- )
458
- allocated_images << one_i
459
- rc = one_i.allocate(image_import[:template],
460
- datastore_found['ID'].to_i, false)
461
-
462
- if OpenNebula.is_error?(rc)
463
- error = ' Error creating disk from '\
464
- "template: #{rc.message}\n"
465
- break
466
- end
467
-
468
- # Monitor image, we need READY state
469
- one_i.info
470
- start_time = Time.now
471
-
472
- while (one_i.state_str != 'READY') &&
473
- (Time.now - start_time < 300)
474
- sleep 1
475
- one_i.info
476
- end
477
-
478
- # Add info for One template
479
- one_i.info
480
- disk_info << "DISK=[\n"
481
- disk_info << "IMAGE_ID=\"#{one_i['ID']}\",\n"
482
- disk_info << "OPENNEBULA_MANAGED=\"NO\"\n"
483
- disk_info << "]\n"
484
-
485
- images.push(image_name)
486
- end
487
- end
488
- rescue StandardError => e
489
- error = "\n There was an error trying to create an "\
490
- 'image for disk in vcenter template. '\
491
- "Reason: #{e.message}"
492
-
493
- if VCenterDriver::CONFIG[:debug_information]
494
- error += "\n\n#{e.backtrace}"
495
- end
496
- ensure
497
- unlock
498
- if !error.empty? && allocated_images
499
- # Rollback delete disk images
500
- allocated_images.each do |i|
501
- i.delete
502
- end
503
- end
504
- end
505
-
506
- [error, disk_info, allocated_images]
507
- end
508
-
509
- ########################################################################
510
- # Create AR
511
- # @param nic [object] contains properties of the nic
512
- # @param with_id [Boolean] determine if AR will contains AR_ID
513
- # @param ipv4 [string] create the AR with a IPv4 address
514
- # @param ipv6 [string] create the AR with a IPv6 address
515
- #
516
- # * in case of IPv6 we use a standard PREFIX_LENGTH = 64
517
- # * if we pass ipv4 we force nic use that IPv4
518
- # * if we pass ipv6 we force nic use that IPv6
519
- # @return ar_tmp
520
- ########################################################################
521
- def create_ar(nic, with_id = false, ipv4 = nil, ipv6 = nil)
522
- ar_tmp = "AR=[\n"
523
-
524
- # if ipv4 and ipv6 are defined create a IPv4 address with a static
525
- # IPv6 address
526
- if ipv4 && ipv6
527
- ar_tmp << "TYPE=\"IP4_6_STATIC\",\n"
528
- ar_tmp << "IP=\"#{ipv4}\",\n"
529
- ar_tmp << "IP6=\"#{ipv6}\",\n"
530
- ar_tmp << "PREFIX_LENGTH=\"64\",\n"
531
- # if just ipv4 is defined create a AR with just a IPv4 address
532
- elsif ipv4
533
- ar_tmp << "TYPE=\"IP4\",\n"
534
- ar_tmp << "IP=\"#{ipv4}\",\n"
535
- # if just ipv6 is defined create a AR with just a IPv4 address
536
- elsif ipv6
537
- ar_tmp << "TYPE=\"IP6_STATIC\",\n"
538
- ar_tmp << "IP6=\"#{ipv6}\",\n"
539
- ar_tmp << "PREFIX_LENGTH=\"64\",\n"
540
- # in case nic have defined mac, ipv4 and ipv6 create a AR with
541
- # this configuration
542
- elsif nic[:mac] && nic[:ipv4] && nic[:ipv6]
543
- ar_tmp << "AR_ID=0,\n" if with_id
544
- ar_tmp << "TYPE=\"IP4_6_STATIC\",\n"
545
- ar_tmp << "IP=\"#{nic[:ipv4]}\",\n"
546
- ar_tmp << "MAC=\"#{nic[:mac]}\",\n"
547
- ar_tmp << "IP6=\"#{nic[:ipv6]}\",\n"
548
- ar_tmp << "PREFIX_LENGTH=\"64\",\n"
549
- # in case nic have defined mac and ipv6 create a AR with
550
- # this configuration
551
- elsif nic[:mac] && nic[:ipv6]
552
- ar_tmp << "AR_ID=0,\n" if with_id
553
- ar_tmp << "TYPE=\"IP6_STATIC\",\n"
554
- ar_tmp << "MAC=\"#{nic[:mac]}\",\n"
555
- ar_tmp << "IP6=\"#{nic[:ipv6]}\",\n"
556
- ar_tmp << "PREFIX_LENGTH=\"64\",\n"
557
- # in case nic have defined mac and ipv4 create a AR with
558
- # this configuration
559
- elsif nic[:mac] && nic[:ipv4]
560
- ar_tmp << "AR_ID=0,\n" if with_id
561
- ar_tmp << "TYPE=\"IP4\",\n"
562
- ar_tmp << "IP=\"#{nic[:ipv4]}\",\n"
563
- ar_tmp << "MAC=\"#{nic[:mac]}\",\n"
564
- # in case nic not have any default configuration create ETHER
565
- else
566
- ar_tmp << "AR_ID=0,\n" if with_id
567
- ar_tmp << "TYPE=\"ETHER\",\n"
568
- ar_tmp << "MAC=\"#{nic[:mac]}\",\n"
569
- end
570
-
571
- ar_tmp << "SIZE=\"1\"\n"
572
- ar_tmp << "]\n"
573
-
574
- ar_tmp
575
- end
576
-
577
- def save_ar_ids(network_found, nic, ar_ids)
578
- value = []
579
- ars_new = network_found.to_hash['VNET']['AR_POOL']['AR']
580
- ars_new = [ars_new] if ars_new.class.to_s.eql? 'Hash'
581
- last_id = ars_new.last['AR_ID']
582
- if ar_ids.key?(nic[:net_ref])
583
- ref = nic[:net_ref]
584
- value = ar_ids[ref.to_s]
585
- end
586
-
587
- value.insert(value.length, last_id)
588
- ar_ids.store(nic[:net_ref], value)
589
-
590
- last_id
591
- end
592
-
593
- def find_alias_ips_in_network(
594
- network,
595
- vm_object,
596
- alias_ipv4 = nil,
597
- alias_ipv6 = nil
598
- )
599
- ipv4 = ipv6 = ''
600
- return unless vm_object.is_a?(VCenterDriver::VirtualMachine)
601
-
602
- ip = nil
603
-
604
- network.info
605
-
606
- unless alias_ipv4.nil?
607
- ip = IPAddr.new(alias_ipv4)
608
- end
609
-
610
- unless alias_ipv6.nil?
611
- ip = IPAddr.new(alias_ipv6)
612
- end
613
-
614
- if ip.nil?
615
- return [ipv4, ipv6]
616
- end
617
-
618
- ar_array = network.to_hash['VNET']['AR_POOL']['AR']
619
- ar_array = [ar_array] if ar_array.is_a?(Hash)
620
- ipv4, ipv6 = find_ip_in_ar(ip, ar_array) if ar_array
621
-
622
- [ipv4, ipv6]
623
- end
624
-
625
- def find_ips_in_network(
626
- network,
627
- vm_object,
628
- nic,
629
- force = false,
630
- first_ip = false
631
- )
632
- ipv4 = ipv6 = ''
633
- ar_id = -1
634
- return unless vm_object.is_a?(VCenterDriver::VirtualMachine)
635
-
636
- network.info
637
-
638
- if nic[:ipv4] || nic[:ipv6]
639
- ar_array = network.to_hash['VNET']['AR_POOL']['AR']
640
- ar_array = [ar_array] if ar_array.is_a?(Hash)
641
-
642
- ipv4, _ipv6, _arid = find_ip_in_ar(
643
- IPAddr.new(nic[:ipv4]),
644
- ar_array
645
- ) if ar_array && nic[:ipv4]
646
-
647
- _ipv4, ipv6, _arid = find_ip_in_ar(
648
- IPAddr.new(nic[:ipv6]),
649
- ar_array
650
- ) if ar_array && nic[:ipv6]
651
-
652
- return [ipv4, ipv6]
653
- end
654
-
655
- # Iterate over Retrieve vCenter VM NICs
656
- unless vm_object.item.guest.net.empty?
657
- vm_object.item.guest.net.each do |net|
658
- mac = net.macAddress
659
- next unless nic[:mac] == mac
660
- next unless net.ipConfig
661
- next if net.ipConfig.ipAddress.empty?
662
-
663
- net.ipConfig.ipAddress.each do |ip_config|
664
- ip = IPAddr.new(ip_config.ipAddress)
665
-
666
- if ip.ipv6? && get_ipv6_prefix(ip.to_s, 10) == 'fe80'
667
- next
668
- end
669
-
670
- if force
671
- ipv4 = ip.to_s if ip.ipv4?
672
- ipv6 = ip.to_s if ip.ipv6?
673
- return [ipv4, ipv6]
674
- end
675
-
676
- ar_array = network.to_hash['VNET']['AR_POOL']['AR']
677
- ar_array = [ar_array] if ar_array.is_a?(Hash)
678
- ipv4, ipv6, ar_id = find_ip_in_ar(ip,
679
- ar_array) if ar_array
680
-
681
- if first_ip
682
- return [ipv4, ipv6, ar_id]
683
- end
684
-
685
- break if (ipv4 !='') || (ipv6 != '')
686
- end
687
- break
688
- end
689
- end
690
- [ipv4, ipv6, ar_id]
691
- end
692
-
693
- def find_ip_in_ar(ip, ar_array)
694
- ipv4 = ipv6 = ''
695
- ar_id = -1
696
- ar_array.each do |ar|
697
- first_condition = ar.key?('IP') && ar.key?('IP_END')
698
- second_condition = ar.key?('IP6') && ar.key?('IP6_END')
699
-
700
- next unless first_condition || second_condition
701
-
702
- start_ip = IPAddr.new(ar['IP']) unless ar['IP'].nil?
703
- end_ip = IPAddr.new(ar['IP_END']) unless ar['IP_END'].nil?
704
- start_ip = IPAddr.new(ar['IP6']) unless ar['IP6'].nil?
705
- end_ip = IPAddr.new(ar['IP6_END']) unless ar['IP6_END'].nil?
706
-
707
- next unless ip.family == start_ip.family &&
708
- ip.family == end_ip.family
709
-
710
- next unless ip >= start_ip && ip <= end_ip
711
-
712
- ipv4 = ip.to_s if ip.ipv4?
713
- ipv6 = ip.to_s if ip.ipv6?
714
- ar_id = ar['ID']
715
- end
716
- [ipv4, ipv6, ar_id]
717
- end
718
-
719
- def nic_alias_from_nic(id, nic, nic_index, network_found, vm_object)
720
- nic_tmp = ''
721
-
722
- nic_alias_index = 0
723
- if nic[:ipv4_additionals]
724
- nic[:ipv4_additionals].split(',').each do |ipv4_additional|
725
- ipv4, ipv6 =
726
- find_alias_ips_in_network(
727
- network_found,
728
- vm_object,
729
- ipv4_additional
730
- )
731
- if ipv4.empty? && ipv6.empty?
732
- ar_tmp = create_ar(
733
- nic,
734
- false,
735
- ipv4_additional
736
- )
737
- network_found.add_ar(ar_tmp)
738
- end
739
- network_found.info
740
-
741
- nic_tmp << "NIC_ALIAS=[\n"
742
- nic_tmp << "NETWORK_ID=\"#{id}\",\n"
743
- nic_tmp << "IP=\"#{ipv4_additional}\",\n"
744
- nic_tmp <<
745
- "NAME=\"VC_NIC#{nic_index}_ALIAS#{nic_alias_index}\",\n"
746
- nic_tmp << "PARENT=\"VC_NIC#{nic_index}\"\n"
747
- nic_tmp << "]\n"
748
- nic_alias_index += 1
749
- end
750
- end
751
- if nic[:ipv6_additionals]
752
- nic[:ipv6_additionals].split(',').each do |ipv6_additional|
753
- ipv4, ipv6 = find_alias_ips_in_network(
754
- network_found,
755
- vm_object,
756
- ipv6_additional
757
- )
758
- if ipv4.empty? && ipv6.empty?
759
- ar_tmp = create_ar(
760
- nic,
761
- false,
762
- nil,
763
- ipv6_additional
764
- )
765
- network_found.add_ar(ar_tmp)
766
- end
767
- network_found.info
768
-
769
- nic_tmp << "NIC_ALIAS=[\n"
770
- nic_tmp << "NETWORK_ID=\"#{id}\",\n"
771
- nic_tmp << "IP6=\"#{ipv6_additional}\",\n"
772
- nic_tmp <<
773
- "NAME=\"VC_NIC#{nic_index}_ALIAS#{nic_alias_index}\",\n"
774
- nic_tmp << "PARENT=\"VC_NIC#{nic_index}\"\n"
775
- nic_tmp << "]\n"
776
- nic_alias_index += 1
777
- end
778
- end
779
-
780
- nic_tmp
781
- end
782
-
783
- def nic_from_network_created(one_vn, nic, nic_index, vm_object, _ar_ids)
784
- nic_tmp = "NIC=[\n"
785
- nic_tmp << "NETWORK_ID=\"#{one_vn.id}\",\n"
786
- nic_tmp << "NAME =\"VC_NIC#{nic_index}\",\n"
787
- nic_tmp << "IP = \"#{nic[:ipv4]}\",\n" if nic[:ipv4]
788
-
789
- if vm?
790
- if nic[:mac] && !nic[:ipv4]
791
- nic_tmp << "MAC=\"#{nic[:mac]}\",\n"
792
- end
793
- if nic[:ipv4_additionals]
794
- nic_tmp <<
795
- 'VCENTER_ADDITIONALS_IP4'\
796
- "=\"#{nic[:ipv4_additionals]}\",\n"
797
- end
798
- if nic[:ipv6]
799
- nic_tmp <<
800
- "VCENTER_IP6=\"#{nic[:ipv6]}\",\n"
801
- end
802
- if nic[:ipv6_global]
803
- nic_tmp <<
804
- "IP6_GLOBAL=\"#{nic[:ipv6_global]}\",\n"
805
- end
806
- if nic[:ipv6_ula]
807
- nic_tmp <<
808
- "IP6_ULA=\"#{nic[:ipv6_ula]}\",\n"
809
- end
810
- if nic[:ipv6_additionals]
811
- nic_tmp <<
812
- 'VCENTER_ADDITIONALS_IP6'\
813
- "=\"#{nic[:ipv6_additionals]}\",\n"
814
- end
815
- end
816
-
817
- nic_tmp << "OPENNEBULA_MANAGED=\"NO\"\n"
818
- nic_tmp << "]\n"
819
-
820
- if vm?
821
- nic_tmp << nic_alias_from_nic(one_vn.id, nic, nic_index,
822
- one_vn, vm_object)
823
- end
824
-
825
- nic_tmp
826
- end
827
-
828
- def nic_from_network_found(
829
- network_found,
830
- vm_object,
831
- nic,
832
- _ar_ids,
833
- nic_index
834
- )
835
- nic_tmp = "NIC=[\n"
836
- nic_tmp << "NETWORK_ID=\"#{network_found['ID']}\",\n"
837
- nic_tmp << "NAME =\"VC_NIC#{nic_index}\",\n"
838
-
839
- if vm?
840
- ipv4, ipv6 = find_ips_in_network(network_found, vm_object,
841
- nic, false, true)
842
- if ipv4.empty? && ipv6.empty?
843
- ar_tmp = create_ar(nic)
844
- network_found.add_ar(ar_tmp)
845
- end
846
-
847
- ipv4, ipv6 = find_ips_in_network(network_found, vm_object,
848
- nic, true)
849
- network_found.info
850
-
851
- if nic[:mac]
852
- nic_tmp << "MAC_IMPORTED=\"#{nic[:mac]}\",\n"
853
- end
854
- # This is the existing nic info
855
- if nic[:mac] && ipv4.empty? && ipv6.empty?
856
- nic_tmp << "MAC=\"#{nic[:mac]}\",\n"
857
- end
858
-
859
- nic_tmp << "IP=\"#{ipv4}\"," unless ipv4.empty?
860
- nic_tmp << "IP6=\"#{ipv6}\"," unless ipv6.empty?
861
-
862
- if nic[:ipv4_additionals]
863
- nic_tmp <<
864
- 'VCENTER_ADDITIONALS_IP4'\
865
- "=\"#{nic[:ipv4_additionals]}\",\n"
866
- end
867
- if nic[:ipv6]
868
- nic_tmp << "VCENTER_IP6=\"#{nic[:ipv6]}\",\n"
869
- end
870
-
871
- if nic[:ipv6_global]
872
- nic_tmp << "IP6_GLOBAL=\"#{nic[:ipv6_global]}\",\n"
873
- end
874
-
875
- if nic[:ipv6_ula]
876
- nic_tmp << "IP6_ULA=\"#{nic[:ipv6_ula]}\",\n"
877
- end
878
-
879
- if nic[:ipv6_additionals]
880
- nic_tmp <<
881
- 'VCENTER_ADDITIONALS_IP6'\
882
- "=\"#{nic[:ipv6_additionals]}\",\n"
883
- end
884
- end
885
-
886
- nic_tmp << "OPENNEBULA_MANAGED=\"NO\"\n"
887
- nic_tmp << "]\n"
888
-
889
- if vm?
890
- nic_tmp <<
891
- nic_alias_from_nic(
892
- network_found['ID'],
893
- nic,
894
- nic_index,
895
- network_found,
896
- vm_object
897
- )
898
- end
899
-
900
- nic_tmp
901
- end
902
-
903
- # Creates an OpenNebula Virtual Network as part of the VM Template
904
- # import process. This only need to happen if no VNET in OpenNebula
905
- # is present that refers to the network where the NIC of the VM Template
906
- # is hooked to.
907
- def create_network_for_import(
908
- opts
909
- )
910
- nic = opts[:nic]
911
- ccr_ref = opts[:ccr_ref]
912
- ccr_name = opts[:ccr_name]
913
- vc_uuid = opts[:vc_uuid]
914
- vcenter_instance_name = opts[:vcenter_instance_name]
915
- dc_name = opts[:dc_name]
916
- template_ref = opts[:template_ref]
917
- dc_ref = opts[:dc_ref]
918
- vm_id = opts[:vm_id]
919
- hpool = opts[:hpool]
920
- vi_client = opts[:vi_client]
921
-
922
- config = {}
923
- config[:refs] = nic[:refs]
924
-
925
- # Let's get the OpenNebula hosts ids
926
- # associated to the clusters references
927
- config[:one_ids] = nic[:refs].map do |ref|
928
- VCenterDriver::VIHelper
929
- .find_by_ref(
930
- OpenNebula::HostPool,
931
- 'TEMPLATE/VCENTER_CCR_REF',
932
- ref,
933
- vc_uuid,
934
- hpool
935
- )['CLUSTER_ID'] rescue -1
936
- end
937
-
938
- if vm?
939
- unmanaged = 'wild'
940
- else
941
- unmanaged = 'template'
942
- end
943
-
944
- net = VCenterDriver::Network
945
- .new_from_ref(
946
- nic[:net_ref],
947
- vi_client
948
- )
949
- if net
950
- vid = VCenterDriver::Network.retrieve_vlanid(net.item)
951
- end
952
- case nic[:pg_type]
953
- # Distributed PortGroups
954
- when VCenterDriver::Network::NETWORK_TYPE_DPG
955
- config[:sw_name] =
956
- nic[:network]
957
- .config
958
- .distributedVirtualSwitch
959
- .name
960
- # For DistributedVirtualPortgroups
961
- # there is networks and uplinks
962
- config[:uplink] = false
963
- # NSX-V PortGroups
964
- when VCenterDriver::Network::NETWORK_TYPE_NSXV
965
- config[:sw_name] =
966
- nic[:network]
967
- .config
968
- .distributedVirtualSwitch
969
- .name
970
- # For NSX-V ( is the same as
971
- # DistributedVirtualPortgroups )
972
- # there is networks and uplinks
973
- config[:uplink] = false
974
-
975
- host_id = vi_client.instance_variable_get '@host_id'
976
-
977
- begin
978
- nsx_client = NSXDriver::NSXClient.new_from_id(host_id)
979
- rescue StandardError
980
- nsx_client = nil
981
- end
982
-
983
- if !nsx_client.nil?
984
- nsx_net = NSXDriver::VirtualWire
985
- .new_from_name(nsx_client, nic[:net_name])
986
- config[:nsx_id] = nsx_net.ls_id
987
- config[:nsx_vni] = nsx_net.ls_vni
988
- config[:nsx_tz_id] = nsx_net.tz_id
989
- end
990
- # Standard PortGroups
991
- when VCenterDriver::Network::NETWORK_TYPE_PG
992
- # There is no uplinks for standard portgroups,
993
- # so all Standard
994
- # PortGroups are networks and no uplinks
995
- config[:uplink] = false
996
- config[:sw_name] = VCenterDriver::Network
997
- .virtual_switch(nic[:network])
998
- # NSX-T PortGroups
999
- when VCenterDriver::Network::NETWORK_TYPE_NSXT
1000
- config[:sw_name] = \
1001
- nic[:network].summary.opaqueNetworkType
1002
- # There is no uplinks for NSX-T networks,
1003
- # so all NSX-T networks
1004
- # are networks and no uplinks
1005
- config[:uplink] = false
1006
-
1007
- host_id = vi_client.instance_variable_get '@host_id'
1008
-
1009
- begin
1010
- nsx_client = NSXDriver::NSXClient.new_from_id(host_id)
1011
- rescue StandardError
1012
- nsx_client = nil
1013
- end
1014
-
1015
- if !nsx_client.nil?
1016
- nsx_net =
1017
- NSXDriver::OpaqueNetwork
1018
- .new_from_name(nsx_client, nic[:net_name])
1019
-
1020
- config[:nsx_id] = nsx_net.ls_id
1021
- config[:nsx_vni] = nsx_net.ls_vni
1022
- config[:nsx_tz_id] = nsx_net.tz_id
1023
- end
1024
- else
1025
- raise "Unknown network type: #{nic[:pg_type]}"
1026
- end
1027
-
1028
- import_opts = {
1029
- :network_name=> nic[:net_name],
1030
- :sw_name=> config[:sw_name],
1031
- :network_ref=> nic[:net_ref],
1032
- :network_type=> nic[:pg_type],
1033
- :ccr_ref=> ccr_ref,
1034
- :ccr_name=> ccr_name,
1035
- :vcenter_uuid=> vc_uuid,
1036
- :vcenter_instance_name=> vcenter_instance_name,
1037
- :dc_name=> dc_name,
1038
- :unmanaged=> unmanaged,
1039
- :template_ref=> template_ref,
1040
- :dc_ref=> dc_ref,
1041
- :template_id=> vm_id
1042
- }
1043
-
1044
- if [VCenterDriver::Network::NETWORK_TYPE_NSXV,
1045
- VCenterDriver::Network::NETWORK_TYPE_NSXT].include?(nic[:pg_type])
1046
- import_opts[:nsx_id] = config[:nsx_id]
1047
- import_opts[:nsx_vni] = config[:nsx_vni]
1048
- import_opts[:nsx_tz_id] = config[:nsx_tz_id]
1049
- end
1050
-
1051
- if vid
1052
- vlanid = VCenterDriver::Network.vlanid(vid)
1053
-
1054
- # we have vlan id
1055
- if /\A\d+\z/.match(vlanid)
1056
- import_opts[:vlanid] = vlanid
1057
- end
1058
- end
1059
-
1060
- # Prepare the Virtual Network template
1061
- one_vnet = VCenterDriver::Network.to_one_template(import_opts)
1062
-
1063
- # always has to be created because of
1064
- # templates when they are instantiated
1065
- ar_tmp = ''
1066
- ar_tmp << "AR=[\n"
1067
- ar_tmp << "TYPE=\"ETHER\",\n"
1068
- ar_tmp << "SIZE=255\n"
1069
- ar_tmp << "]\n"
1070
-
1071
- if vm?
1072
- ar_tmp << create_ar(nic, false, nic[:ipv4]) if nic[:ipv4]
1073
-
1074
- if nic[:ipv6]
1075
- ar_tmp << create_ar(nic, false, nil, nic[:ipv6])
1076
- end
1077
-
1078
- ar_tmp << create_ar(nic, true) if !nic[:ipv4] && !nic[:ipv6]
1079
- end
1080
-
1081
- one_vnet[:one] << ar_tmp
1082
- config[:one_object] = one_vnet[:one]
1083
- _cluster_id = VCenterDriver::VIHelper
1084
- .get_cluster_id(config[:one_ids])
1085
-
1086
- one_vn = VCenterDriver::Network.create_one_network(config)
1087
- VCenterDriver::VIHelper.clean_ref_hash
1088
- one_vn.info
1089
-
1090
- # Wait until the virtual network is in ready state
1091
- t_start = Time.now
1092
- error = false
1093
- timeout = 30
1094
-
1095
- while Time.now - t_start < timeout
1096
- begin
1097
- if one_vn.short_state_str == 'rdy'
1098
- error = false
1099
- break
1100
- end
1101
- rescue StandardError
1102
- error = true
1103
- end
1104
-
1105
- sleep 1
1106
- one_vn.info
1107
- end
1108
-
1109
- if error
1110
- error_msg = "VNET #{one_vn.id} in state "
1111
- error_msg += "#{one_vn.short_state_str}, aborting import"
1112
- raise error_msg
1113
- end
1114
-
1115
- one_vn
1116
- end
1117
-
1118
- def import_vcenter_nics(opts, vm_id = nil, dc_name = nil)
1119
- vi_client = opts[:vi_client]
1120
- vc_uuid = opts[:vc_uuid]
1121
- npool = opts[:npool]
1122
- hpool = opts[:hpool]
1123
- vcenter_instance_name = opts[:vcenter]
1124
- template_ref = opts[:template_moref]
1125
- vm_object = opts[:vm_object]
1126
-
1127
- nic_info = ''
1128
- error = ''
1129
- ar_ids = {}
1130
- begin
1131
- # Lock import operation, to avoid
1132
- # concurrent creation of networks
1133
- lock
1134
-
1135
- if !dc_name
1136
- dc = datacenter
1137
- dc_name = dc.item.name
1138
- dc_ref = dc.item._ref
1139
- end
1140
-
1141
- ccr_ref = self['runtime.host.parent._ref']
1142
- ccr_name = self['runtime.host.parent.name']
1143
-
1144
- # Get nics and info required
1145
- vc_nics = vcenter_nics_hash
1146
-
1147
- # Track allocated networks for rollback
1148
- allocated_networks = []
1149
-
1150
- nic_index = 0
1151
-
1152
- vc_nics.each do |nic|
1153
- [:ipv4, :ipv6].each do |type|
1154
- if nic[type]
1155
- opts[type].shift if opts[type]
1156
- next
1157
- end
1158
-
1159
- begin
1160
- ip = opts[type].shift if opts[type]
1161
-
1162
- # Check if it is a valid IP
1163
- IPAddr.new(ip)
1164
-
1165
- nic[type] = ip
1166
- rescue StandardError
1167
- end
1168
- end
1169
-
1170
- # Check if the network already exists
1171
- network_found =
1172
- VCenterDriver::VIHelper
1173
- .find_by_ref(
1174
- OpenNebula::VirtualNetworkPool,
1175
- 'TEMPLATE/VCENTER_NET_REF',
1176
- nic[:net_ref],
1177
- vc_uuid,
1178
- npool
1179
- )
1180
- # Network is already in OpenNebula
1181
- if network_found
1182
- nic_info << nic_from_network_found(network_found,
1183
- vm_object,
1184
- nic,
1185
- ar_ids,
1186
- nic_index.to_s)
1187
- # Network not found
1188
- else
1189
- opts = {
1190
- :nic => nic,
1191
- :ccr_ref => ccr_ref,
1192
- :ccr_name => ccr_name,
1193
- :vc_uuid => vc_uuid,
1194
- :vcenter_instance_name => vcenter_instance_name,
1195
- :dc_name => dc_name,
1196
- :template_ref => template_ref,
1197
- :dc_ref => dc_ref,
1198
- :vm_id => vm_id,
1199
- :hpool => hpool,
1200
- :vi_client => vi_client
1201
- }
1202
-
1203
- one_vn = create_network_for_import(
1204
- opts
1205
- )
1206
-
1207
- allocated_networks << one_vn
1208
-
1209
- nic_info << nic_from_network_created(
1210
- one_vn,
1211
- nic,
1212
- nic_index.to_s,
1213
- vm_object,
1214
- ar_ids
1215
- )
1216
-
1217
- # Refresh npool
1218
- npool.info_all
1219
- end
1220
- nic_index += 1
1221
- end
1222
- rescue StandardError => e
1223
- error = "\n There was an error trying to create \
1224
- a virtual network to repesent a \
1225
- vCenter network for a VM or VM Template. \
1226
- Reason: #{e.message}"
1227
- ensure
1228
- unlock
1229
- # Rollback, delete virtual networks
1230
- if !error.empty? && allocated_networks
1231
- allocated_networks.each do |n|
1232
- n.delete
1233
- end
1234
- end
1235
- end
1236
-
1237
- [error, nic_info, ar_ids, allocated_networks]
1238
- end
1239
-
1240
- def get_vcenter_disk_key(unit_number, controller_key)
1241
- key = nil
1242
-
1243
- @item['config.hardware.device'].each do |device|
1244
- disk = {}
1245
-
1246
- next unless disk_or_iso?(device)
1247
-
1248
- disk[:device] = device
1249
- next unless device.controllerKey == controller_key &&
1250
- device.unitNumber == unit_number
1251
-
1252
- key = device.key
1253
- break
1254
- end
1255
-
1256
- key
1257
- end
1258
-
1259
- def vcenter_disks_get
1260
- disks = []
1261
- ide_controlled = []
1262
- sata_controlled = []
1263
- scsi_controlled = []
1264
- controller = {}
1265
-
1266
- @item['config.hardware.device'].each do |device|
1267
- disk = {}
1268
-
1269
- if device.is_a? RbVmomi::VIM::VirtualIDEController
1270
- ide_controlled.concat(device.device)
1271
- controller[device.key] = "ide#{device.busNumber}"
1272
- end
1273
-
1274
- if device.is_a? RbVmomi::VIM::VirtualSATAController
1275
- sata_controlled.concat(device.device)
1276
- controller[device.key] = "sata#{device.busNumber}"
1277
- end
1278
-
1279
- if device.is_a? RbVmomi::VIM::VirtualSCSIController
1280
- scsi_controlled.concat(device.device)
1281
- controller[device.key] = "scsi#{device.busNumber}"
1282
- end
1283
-
1284
- next unless disk_or_iso?(device)
1285
-
1286
- disk[:device] = device
1287
-
1288
- unless device.backing.datastore
1289
- raise "datastore not found for VM's device"
1290
- end
1291
-
1292
- disk[:datastore] =
1293
- device.backing.datastore
1294
- disk[:path] =
1295
- device.backing.fileName
1296
- disk[:path_wo_ds]=
1297
- disk[:path].sub(/^\[(.*?)\] /, '')
1298
- disk?(device) ? disk[:type] = 'OS' : disk[:type] = 'CDROM'
1299
- disk[:key] =
1300
- device.key
1301
- if ide_controlled.include?(device.key)
1302
- disk[:prefix] = 'hd'
1303
- end
1304
- if scsi_controlled.include?(device.key)
1305
- disk[:prefix] = 'sd'
1306
- end
1307
- if sata_controlled.include?(device.key)
1308
- disk[:prefix] = 'sd'
1309
- end
1310
- disk[:tag] =
1311
- "#{controller[device.controllerKey]}:#{device.unitNumber}"
1312
-
1313
- disks << disk
1314
- end
1315
-
1316
- disks
1317
- end
1318
-
1319
- def vcenter_nics_list
1320
- nics = []
1321
- @item.config.hardware.device.each do |device|
1322
- nics << device if VCenterDriver::Network.nic?(device)
1323
- end
1324
-
1325
- nics
1326
- end
1327
-
1328
- def identify_network(identifier, network)
1329
- if network.class == RbVmomi::VIM::DistributedVirtualPortgroup
1330
- return network if identifier == network.key
1331
-
1332
- return
1333
- end
1334
-
1335
- if network.class == RbVmomi::VIM::Network
1336
- return network if identifier == network
1337
-
1338
- return
1339
- end
1340
-
1341
- return unless network.class == RbVmomi::VIM::OpaqueNetwork
1342
-
1343
- if identifier == network.summary.opaqueNetworkId
1344
- network
1345
- else
1346
- nil
1347
- end
1348
- end
1349
-
1350
- def retrieve_from_device(device)
1351
- device_network = nil
1352
- device_network_id = nil
1353
- # First search network corresponding this device
1354
- # Distributed Networks and NSX-V Networks
1355
- if !device.backing[:port].nil?
1356
- device_network_id = device.backing.port.portgroupKey
1357
- # Standard Networks
1358
- elsif !device.backing[:network].nil?
1359
- device_network_id = device.backing[:network]
1360
- # NSX-T Opaque Networks
1361
- elsif !device.backing[:opaqueNetworkId].nil?
1362
- device_network_id = device.backing[:opaqueNetworkId]
1363
- end
1364
-
1365
- # Check if networkId exists
1366
- if device_network_id.nil?
1367
- raise "Invalid or not supported network #{device.backing}"
1368
- end
1369
-
1370
- # Matching between device and network objects
1371
- @item.network.each do |net|
1372
- device_network = identify_network(device_network_id, net)
1373
- break unless device_network.nil?
1374
- end
1375
-
1376
- # Check network matching
1377
- if device_network.nil?
1378
- raise "\"#{device.deviceInfo.label}\" \
1379
- not match any known network"
1380
- end
1381
-
1382
- res = {}
1383
-
1384
- res[:refs] = device_network.host.map do |h|
1385
- h.parent._ref if h.parent
1386
- end
1387
-
1388
- res[:net_name] =
1389
- device_network.name
1390
- res[:net_ref] =
1391
- device_network._ref
1392
- res[:pg_type] =
1393
- VCenterDriver::Network
1394
- .get_network_type(
1395
- device_network,
1396
- res[:net_name]
1397
- )
1398
- res[:network] =
1399
- device_network
1400
-
1401
- res
1402
- end
1403
-
1404
- def vcenter_nics_hash
1405
- parse_live = lambda {|inets_raw|
1406
- h = nil
1407
- begin
1408
- h = inets_raw.to_h
1409
- rescue NoMethodError
1410
- h = {}
1411
- inets_raw.each do |nic_dev|
1412
- h[nic_dev[0]] = nic_dev[1]
1413
- end
1414
- end
1415
-
1416
- return h
1417
- }
1418
-
1419
- nics = []
1420
- inets_raw = nil
1421
- inets = {}
1422
-
1423
- @item['config.hardware.device'].each do |device|
1424
- next unless VCenterDriver::Network.nic?(device)
1425
-
1426
- nic = retrieve_from_device(device)
1427
- nic[:mac] = device.macAddress rescue nil
1428
-
1429
- if vm? && online?
1430
- inets_raw ||=
1431
- @item['guest.net']
1432
- .map
1433
- .with_index {|x, _| [x.macAddress, x] }
1434
- inets = parse_live.call(inets_raw) if inets.empty?
1435
-
1436
- if !inets[nic[:mac]].nil?
1437
- ip_addresses =
1438
- inets[nic[:mac]]
1439
- .ipConfig
1440
- .ipAddress rescue nil
1441
- end
1442
-
1443
- if !ip_addresses.nil? && !ip_addresses.empty?
1444
- nic[:ipv4],
1445
- nic[:ipv4_additionals] = nil
1446
- nic[:ipv6],
1447
- nic[:ipv6_ula],
1448
- nic[:ipv6_global],
1449
- nic[:ipv6_additionals] = nil
1450
- fill_nic(ip_addresses, nic)
1451
- end
1452
- end
1453
- nics << nic
1454
- end
1455
-
1456
- nics
1457
- end
1458
-
1459
- def fill_nic(ip_addresses, nic)
1460
- (0...ip_addresses.length).each do |i|
1461
- ip = ip_addresses[i].ipAddress
1462
- if ip =~ Resolv::IPv4::Regex
1463
- if nic[:ipv4]
1464
- if nic[:ipv4_additionals]
1465
- nic[:ipv4_additionals] += ',' + ip
1466
- else
1467
- nic[:ipv4_additionals] = ip
1468
- end
1469
- else
1470
- nic[:ipv4] = ip
1471
- end
1472
- elsif ip_addresses[i].ipAddress =~ Resolv::IPv6::Regex
1473
- if get_ipv6_prefix(ip, 10) == 'fe80'
1474
- # we not process this address
1475
- elsif get_ipv6_prefix(ip, 7) == 'fc00'
1476
- nic[:ipv6_ula] = ip
1477
- else
1478
- if nic[:ipv6]
1479
- if nic[:ipv6_additionals]
1480
- nic[:ipv6_additionals] += ',' + ip
1481
- else
1482
- nic[:ipv6_additionals] = ip
1483
- end
1484
- else
1485
- nic[:ipv6] = ip
1486
- end
1487
- end
1488
- end
1489
- end
1490
- end
1491
-
1492
- def get_ipv6_prefix(ipv6, prefix_length)
1493
- ip_slice =
1494
- ipv6
1495
- .split(':')
1496
- .map {|elem| elem.hex }
1497
- .map do |elem|
1498
- int, dec = elem.divmod(1)
1499
- bin = int.to_s(2).to_s
1500
-
1501
- while dec > 0
1502
- int, dec = (dec * 2).divmod(1)
1503
- bin << int.to_s
1504
- end
1505
-
1506
- bin
1507
- end.map {|elem| elem.rjust(16, '0') } # rubocop:disable Style/MultilineBlockChain
1508
-
1509
- ip_chain = ip_slice.join
1510
- prefix = ip_chain[0, prefix_length]
1511
-
1512
- cont = 0
1513
- limit = prefix.length
1514
- index = 0
1515
- slices = []
1516
-
1517
- while cont < limit
1518
- slices[index] = prefix.slice(cont, 4)
1519
- slices[index] = slices[index].ljust(4, '0')
1520
- index +=1
1521
- cont+=4
1522
- end
1523
-
1524
- slices.map {|elem| format('%0x', elem.to_i(2)) }
1525
- .join.ljust(4, '0')
1526
- end
1527
-
1528
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk or a cdrom
1529
- def disk_or_cdrom?(device)
1530
- is_disk =
1531
- !device
1532
- .class
1533
- .ancestors
1534
- .index(RbVmomi::VIM::VirtualDisk).nil?
1535
- is_cdrom =
1536
- !device
1537
- .class
1538
- .ancestors
1539
- .index(RbVmomi::VIM::VirtualCdrom).nil?
1540
- is_disk || is_cdrom
1541
- end
1542
-
1543
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk or an iso file
1544
- def disk_or_iso?(device)
1545
- is_disk =
1546
- !device
1547
- .class
1548
- .ancestors
1549
- .index(RbVmomi::VIM::VirtualDisk).nil?
1550
- is_iso =
1551
- device
1552
- .backing
1553
- .is_a? RbVmomi::VIM::VirtualCdromIsoBackingInfo
1554
- is_disk || is_iso
1555
- end
1556
-
1557
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk
1558
- def disk?(device)
1559
- !device.class.ancestors.index(RbVmomi::VIM::VirtualDisk).nil?
1560
- end
1561
-
1562
- def cdrom?(device)
1563
- device.backing.is_a? RbVmomi::VIM::VirtualCdromIsoBackingInfo
1564
- end
1565
-
1566
- # @return RbVmomi::VIM::ResourcePool, first resource pool in cluster
1567
- def resource_pool
1568
- self['runtime.host.parent.resourcePool']
1569
- end
1570
-
1571
- def esx_name
1572
- self['runtime.host.name']
1573
- end
1574
-
1575
- def vm_to_one(vm_name)
1576
- str = "NAME = \"#{vm_name}\"\n"\
1577
- "CPU = \"#{@vm_info['config.hardware.numCPU']}\"\n"\
1578
- "vCPU = \"#{@vm_info['config.hardware.numCPU']}\"\n"\
1579
- "MEMORY = \"#{@vm_info['config.hardware.memoryMB']}\"\n"\
1580
- "HYPERVISOR = \"vcenter\"\n"\
1581
- "CONTEXT = [\n"\
1582
- " NETWORK = \"YES\",\n"\
1583
- " SSH_PUBLIC_KEY = \"$USER[SSH_PUBLIC_KEY]\"\n"\
1584
- "]\n"\
1585
- "VCENTER_INSTANCE_ID =\"#{@vm_info[:vc_uuid]}\"\n"\
1586
- "VCENTER_CCR_REF =\"#{@vm_info[:cluster_ref]}\"\n"
1587
-
1588
- str << "DEPLOY_ID =\"#{self['_ref']}\"\n"
1589
- @state = 'POWEROFF' if @state == 'd'
1590
- str << "IMPORT_STATE =\"#{@state}\"\n"
1591
-
1592
- # Get DS information
1593
- if !@vm_info['datastore'].nil?
1594
- !@vm_info['datastore'].last.nil? &&
1595
- !@vm_info['datastore'].last._ref.nil?
1596
- ds_ref = vm_template_ds_ref
1597
- str << "VCENTER_DS_REF = \"#{ds_ref}\"\n"
1598
- end
1599
-
1600
- vnc_port = nil
1601
- keymap =
1602
- VCenterDriver::VIHelper
1603
- .get_default(
1604
- 'VM/TEMPLATE/GRAPHICS/KEYMAP'
1605
- )
1606
-
1607
- @vm_info['config.extraConfig'].select do |xtra|
1608
- if xtra[:key].downcase=='remotedisplay.vnc.port'
1609
- vnc_port = xtra[:value]
1610
- end
1611
-
1612
- if xtra[:key].downcase=='remotedisplay.vnc.keymap'
1613
- keymap = xtra[:value]
1614
- end
1615
- end
1616
-
1617
- if !@vm_info['config.extraConfig'].empty?
1618
- str << "GRAPHICS = [\n"\
1619
- " TYPE =\"vnc\",\n"
1620
- str << " PORT =\"#{vnc_port}\",\n" if vnc_port
1621
- str << " KEYMAP =\"#{keymap}\",\n" if keymap
1622
- str << " LISTEN =\"0.0.0.0\"\n"
1623
- str << "]\n"
1624
- end
1625
-
1626
- if !@vm_info['config.annotation'] || @vm_info['config.annotation']
1627
- .empty?
1628
- str << 'DESCRIPTION = "vCenter Template \
1629
- imported by OpenNebula' \
1630
- " from Cluster #{@vm_info['cluster_name']}\"\n"
1631
- else
1632
- notes = @vm_info['config.annotation']
1633
- .gsub('\\', '\\\\')
1634
- .gsub('"', '\\"')
1635
- str << "DESCRIPTION = \"#{notes}\"\n"
1636
- end
1637
-
1638
- case @vm_info['guest.guestFullName']
1639
- when /CentOS/i
1640
- str << "LOGO=images/logos/centos.png\n"
1641
- when /Debian/i
1642
- str << "LOGO=images/logos/debian.png\n"
1643
- when /Red Hat/i
1644
- str << "LOGO=images/logos/redhat.png\n"
1645
- when /Ubuntu/i
1646
- str << "LOGO=images/logos/ubuntu.png\n"
1647
- when /Windows XP/i
1648
- str << "LOGO=images/logos/windowsxp.png\n"
1649
- when /Windows/i
1650
- str << "LOGO=images/logos/windows8.png\n"
1651
- when /Linux/i
1652
- str << "LOGO=images/logos/linux.png\n"
1653
- end
1654
-
1655
- str
1656
- end
1657
-
1658
- # Gets MOREF from Datastore used by the VM. It validates
1659
- # the selected DS is not only used to host swap.
1660
- def vm_template_ds_ref
1661
- begin
1662
- ds_ref = nil
1663
- if @vm_info['datastore'].length > 1
1664
- swap_path = ''
1665
- @vm_info['config.extraConfig'].each do |element|
1666
- if element.key == 'sched.swap.derivedName'
1667
- swap_path = element.value
1668
- end
1669
- end
1670
- @vm_info['datastore'].each do |datastore|
1671
- path = datastore.summary.url.sub(%r{ds:///*}, '')
1672
- if !swap_path.include?(path) && !datastore._ref.nil?
1673
- ds_ref = datastore._ref
1674
- break
1675
- end
1676
- end
1677
- elsif @vm_info['datastore'].length == 1
1678
- if !@vm_info['datastore'].first._ref.nil?
1679
- ds_ref = @vm_info['datastore'].first._ref
1680
- end
1681
- end
1682
-
1683
- ds_ref
1684
- rescue StandardError => e
1685
- "Could not find DATASTORE for this VM. Reason: #{e.message}"
1686
- end
1687
- end
1688
-
1689
- def self.template_to_one(
1690
- template,
1691
- vc_uuid,
1692
- ccr_ref,
1693
- ccr_name,
1694
- import_name
1695
- )
1696
- num_cpu, memory, annotation, guest_fullname =
1697
- template
1698
- .item
1699
- .collect(
1700
- 'config.hardware.numCPU',
1701
- 'config.hardware.memoryMB',
1702
- 'config.annotation',
1703
- 'guest.guestFullName'
1704
- )
1705
-
1706
- str = "NAME = \"#{import_name}\"\n"\
1707
- "CPU = \"#{num_cpu}\"\n"\
1708
- "vCPU = \"#{num_cpu}\"\n"\
1709
- "MEMORY = \"#{memory}\"\n"\
1710
- "HYPERVISOR = \"vcenter\"\n"\
1711
- "CONTEXT = [\n"\
1712
- " NETWORK = \"YES\",\n"\
1713
- " SSH_PUBLIC_KEY = \"$USER[SSH_PUBLIC_KEY]\"\n"\
1714
- "]\n"\
1715
- "VCENTER_INSTANCE_ID =\"#{vc_uuid}\"\n"
1716
-
1717
- str << "VCENTER_TEMPLATE_REF =\"#{template['_ref']}\"\n"
1718
- str << "VCENTER_CCR_REF =\"#{ccr_ref}\"\n"
1719
-
1720
- str << "GRAPHICS = [\n"\
1721
- " TYPE =\"vnc\",\n"
1722
- str << " LISTEN =\"0.0.0.0\"\n"
1723
- str << "]\n"
1724
-
1725
- if annotation.nil? || annotation.empty?
1726
- str << 'DESCRIPTION = "vCenter Template imported by OpenNebula'\
1727
- " from Cluster #{ccr_name}\"\n"
1728
- else
1729
- notes = annotation.gsub('\\', '\\\\').gsub('"', '\\"')
1730
- str << "DESCRIPTION = \"#{notes}\"\n"
1731
- end
1732
-
1733
- case guest_fullname
1734
- when /CentOS/i
1735
- str << "LOGO=images/logos/centos.png\n"
1736
- when /Debian/i
1737
- str << "LOGO=images/logos/debian.png\n"
1738
- when /Red Hat/i
1739
- str << "LOGO=images/logos/redhat.png\n"
1740
- when /Ubuntu/i
1741
- str << "LOGO=images/logos/ubuntu.png\n"
1742
- when /Windows XP/i
1743
- str << "LOGO=images/logos/windowsxp.png\n"
1744
- when /Windows/i
1745
- str << "LOGO=images/logos/windows8.png\n"
1746
- when /Linux/i
1747
- str << "LOGO=images/logos/linux.png\n"
1748
- end
1749
-
1750
- str
1751
- end
1752
-
1753
- def self.get_xml_template(
1754
- template,
1755
- vcenter_uuid,
1756
- vi_client,
1757
- dc_name = nil,
1758
- rp_cache = {}
1759
- )
1760
- begin
1761
- template_ref = template['_ref']
1762
- template_name = template['name']
1763
- template_ccr = template['runtime.host.parent']
1764
- template_ccr_ref = template_ccr._ref
1765
- template_ccr_name = template_ccr.name
1766
-
1767
- # Get datacenter info
1768
- if !dc_name
1769
- dc = datacenter
1770
- dc_name = dc.item.name
1771
- end
1772
-
1773
- # Get resource pools and generate a list
1774
- if !rp_cache[template_ccr_name]
1775
- tmp_cluster =
1776
- VCenterDriver::ClusterComputeResource
1777
- .new_from_ref(
1778
- template_ccr_ref,
1779
- vi_client
1780
- )
1781
- rp_list = tmp_cluster.get_resource_pool_list
1782
- rp = ''
1783
- if !rp_list.empty?
1784
- rp_name_list = []
1785
- rp_list.each do |rp_hash|
1786
- rp_name_list << rp_hash[:name]
1787
- end
1788
- rp = 'O|list|Which resource pool \
1789
- you want this VM to run in? '
1790
- rp << "|#{rp_name_list.join(',')}" # List of RP
1791
- rp << "|#{rp_name_list.first}" # Default RP
1792
- end
1793
- rp_cache[template_ccr_name] = {}
1794
- rp_cache[template_ccr_name][:rp] = rp
1795
- rp_cache[template_ccr_name][:rp_list] = rp_list
1796
- end
1797
- rp = rp_cache[template_ccr_name][:rp]
1798
- rp_list = rp_cache[template_ccr_name][:rp_list]
1799
-
1800
- # Determine the location path for the template
1801
- vcenter_template =
1802
- VCenterDriver::VirtualMachine
1803
- .new_without_id(
1804
- vi_client,
1805
- template_ref
1806
- )
1807
- item = vcenter_template.item
1808
- folders = []
1809
- until item.instance_of? RbVmomi::VIM::Datacenter
1810
- item = item.parent
1811
- first_condition =
1812
- !(item.instance_of? RbVmomi::VIM::Datacenter)
1813
- second_condition =
1814
- item.name != 'vm'
1815
-
1816
- if first_condition && second_condition
1817
- folders << item.name
1818
- end
1819
- if item.nil?
1820
- raise 'Could not find the templates parent location'
1821
- end
1822
- end
1823
- location = folders.reverse.join('/')
1824
- location = '/' if location.empty?
1825
-
1826
- # Generate a crypto hash for the template
1827
- # name and take the first 12 chars
1828
- import_name =
1829
- VCenterDriver::VIHelper
1830
- .one_name(
1831
- OpenNebula::TemplatePool,
1832
- template_name,
1833
- template_ref+vcenter_uuid
1834
- )
1835
-
1836
- template_name = template_name.tr("\u007F", '')
1837
- template_ccr_name = template_ccr_name.tr("\u007F", '')
1838
-
1839
- # Prepare the Hash that will be used by importers to display
1840
- # the object being imported
1841
- one_tmp = {}
1842
- one_tmp[:name] = import_name
1843
- one_tmp[:ref] = template_ref
1844
- one_tmp[:dc_name] = dc_name
1845
- one_tmp[:template_name] = template_name
1846
- one_tmp[:sunstone_template_name]=
1847
- "#{template_name} [ Cluster: #{template_ccr_name}" \
1848
- " - Template location: #{location} ]"
1849
- one_tmp[:template_location] = location
1850
- one_tmp[:vcenter_ccr_ref] = template_ccr_ref
1851
- one_tmp[:vcenter_ref] = template_ref
1852
- one_tmp[:vcenter_instance_uuid] = vcenter_uuid
1853
- one_tmp[:cluster_name] = template_ccr_name
1854
- one_tmp[:rp] = rp
1855
- one_tmp[:rp_list] = rp_list
1856
- one_tmp[:template] = template
1857
- # By default we import disks and nics
1858
- one_tmp[:import_disks_and_nics] = true
1859
-
1860
- # Get the host ID of the OpenNebula host
1861
- # which represents the vCenter Cluster
1862
- one_host =
1863
- VCenterDriver::VIHelper
1864
- .find_by_ref(
1865
- OpenNebula::HostPool,
1866
- 'TEMPLATE/VCENTER_CCR_REF',
1867
- template_ccr_ref,
1868
- vcenter_uuid
1869
- )
1870
- host_id = one_host['ID']
1871
- unless host_id
1872
- raise "Could not find the host's ID associated \
1873
- to template being imported"
1874
- end
1875
-
1876
- # Get the OpenNebula's template hash
1877
- one_tmp[:one] =
1878
- template_to_one(
1879
- template,
1880
- vcenter_uuid,
1881
- template_ccr_ref,
1882
- template_ccr_name,
1883
- import_name
1884
- )
1885
- one_tmp
1886
- rescue StandardError
1887
- nil
1888
- end
1889
- end
1890
-
1891
- # TODO: check with uuid
1892
- def self.new_from_ref(ref, vi_client)
1893
- new(RbVmomi::VIM::VirtualMachine.new(vi_client.vim, ref), vi_client)
1894
- end
1895
-
1896
- end
1897
-
1898
- ##########################################################################
1899
- # Class VmImporter
1900
- ##########################################################################
1901
- class VmImporter < VCenterDriver::VcImporter
1902
-
1903
- def initialize(one_client, vi_client)
1904
- super(one_client, vi_client)
1905
- @one_class = OpenNebula::Template
1906
-
1907
- @defaults = {
1908
- :linked_clone => '0',
1909
- :copy => '0',
1910
- :name => '',
1911
- :folder => '',
1912
- :resourcepool => [],
1913
- :type => ''
1914
- }
1915
- end
1916
-
1917
- def get_list(_args = {})
1918
- dc_folder = VCenterDriver::DatacenterFolder.new(@vi_client)
1919
-
1920
- # Get OpenNebula's templates pool
1921
- tpool =
1922
- VCenterDriver::VIHelper
1923
- .one_pool(
1924
- OpenNebula::TemplatePool,
1925
- false
1926
- )
1927
- if tpool.respond_to?(:message)
1928
- raise "Could not get OpenNebula TemplatePool: #{tpool.message}"
1929
- end
1930
-
1931
- @list = dc_folder.get_unimported_templates(@vi_client, tpool)
1932
- end
1933
-
1934
- def rp_opts(type, rps)
1935
- str = ''
1936
-
1937
- return str if (type == 'default') || rps.empty?
1938
-
1939
- if type == 'fixed'
1940
- str << "VCENTER_RESOURCE_POOL=\"#{rps}\"\n"
1941
- else
1942
- default = rps.first
1943
- rps_str = rps.join(',')
1944
-
1945
- str << 'USER_INPUTS=['
1946
- str << "VCENTER_RESOURCE_POOL=\"M|list|resource \
1947
- pool list|#{rps_str}|#{default}\""
1948
- str << ']'
1949
- end
1950
-
1951
- str
1952
- end
1953
-
1954
- def import(selected)
1955
- opts = @info[selected[:ref]][:opts]
1956
- working_template = selected
1957
-
1958
- vcenter = selected[:vcenter]
1959
- vc_uuid = selected[:vcenter_instance_uuid]
1960
- dc = selected[:dc_name]
1961
-
1962
- linked_clone = opts[:linked_clone] == '1'
1963
- copy = opts[:copy] == '1'
1964
- deploy_in_folder = !opts[:folder].empty?
1965
-
1966
- res = { :id => [], :name => selected[:name] }
1967
- dpool, ipool, npool, hpool = create_pools
1968
-
1969
- template =
1970
- VCenterDriver::Template
1971
- .new_from_ref(
1972
- selected[:vcenter_ref],
1973
- @vi_client
1974
- )
1975
- # Linked clones and copy preparation
1976
- if linked_clone
1977
- # reached this point we need to delete
1978
- # the template if something go wrong
1979
- if copy
1980
- error, template_copy_ref =
1981
- selected[:template].save_as_linked_clones(opts[:name])
1982
-
1983
- unless template_copy_ref
1984
- raise 'There is a problem creating ' \
1985
- "your copy: #{error}"
1986
- end
1987
-
1988
- template =
1989
- VCenterDriver::Template
1990
- .new_from_ref(
1991
- template_copy_ref,
1992
- @vi_client
1993
- )
1994
- @rollback <<
1995
- Raction
1996
- .new(
1997
- template,
1998
- :delete_template
1999
- )
2000
-
2001
- one_template =
2002
- VCenterDriver::Template
2003
- .get_xml_template(
2004
- template,
2005
- vc_uuid,
2006
- @vi_client,
2007
- dc
2008
- )
2009
- unless one_template
2010
- raise 'There is a problem obtaining info '\
2011
- "from your template's copy"
2012
- end
2013
-
2014
- working_template = one_template
2015
- end
2016
-
2017
- lc_error, use_lc = template.create_delta_disks
2018
- if lc_error
2019
- raise 'Something was wront with create \
2020
- delta disk operation'
2021
- end
2022
-
2023
- if use_lc
2024
- working_template[:one] <<
2025
- "\nVCENTER_LINKED_CLONES=\"YES\"\n"
2026
- end
2027
- end
2028
-
2029
- if deploy_in_folder
2030
- working_template[:one] <<
2031
- "VCENTER_VM_FOLDER=\"#{opts[:folder]}\"\n"
2032
- end
2033
-
2034
- working_template[:one] <<
2035
- "VCENTER_TEMPLATE_NAME=\"#{selected[:name]}\"\n"
2036
-
2037
- unless copy
2038
- create(working_template[:one]) do |one_object, id|
2039
- res[:id] << id
2040
-
2041
- type = { :object => 'template', :id => id }
2042
- error, template_disks, allocated_images =
2043
- template
2044
- .import_vcenter_disks(
2045
- vc_uuid,
2046
- dpool,
2047
- ipool,
2048
- type
2049
- )
2050
-
2051
- if allocated_images
2052
- # rollback stack
2053
- allocated_images.reverse.each do |i|
2054
- @rollback.unshift(Raction.new(i, :delete))
2055
- end
2056
- end
2057
- raise error unless error.empty?
2058
-
2059
- working_template[:one] << template_disks
2060
-
2061
- if template_copy_ref
2062
- template_moref = template_copy_ref
2063
- else
2064
- template_moref = selected[:vcenter_ref]
2065
- end
2066
-
2067
- opts_nics = {
2068
- :vi_client => @vi_client,
2069
- :vc_uuid => vc_uuid,
2070
- :npool => npool,
2071
- :hpool => hpool,
2072
- :vcenter => vcenter,
2073
- :template_moref => template_moref,
2074
- :vm_object => nil
2075
- }
2076
-
2077
- error, template_nics, _ar_ids, allocated_nets =
2078
- template
2079
- .import_vcenter_nics(
2080
- opts_nics,
2081
- id,
2082
- dc
2083
- )
2084
-
2085
- if allocated_nets
2086
- # rollback stack
2087
- allocated_nets.reverse.each do |n|
2088
- @rollback.unshift(Raction.new(n, :delete))
2089
- end
2090
- end
2091
- raise error unless error.empty?
2092
-
2093
- working_template[:one] << template_nics
2094
- working_template[:one] << rp_opts(
2095
- opts[:type],
2096
- opts[:resourcepool]
2097
- )
2098
-
2099
- one_object.update(working_template[:one])
2100
- end
2101
- end
2102
-
2103
- res
2104
- end
2105
-
2106
- def attr
2107
- 'TEMPLATE/VCENTER_TEMPLATE_REF'
2108
- end
2109
-
2110
- end
2111
-
2112
- end