opennebula 6.10.2 → 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 +12 -40
  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 +4 -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 -2114
  131. data/lib/vmm_importer.rb +0 -165
data/lib/vm_template.rb DELETED
@@ -1,2114 +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 nic[:pg_type] ==
1045
- VCenterDriver::Network::NETWORK_TYPE_NSXV ||
1046
- nic[:pg_type] ==
1047
- VCenterDriver::Network::NETWORK_TYPE_NSXT
1048
- import_opts[:nsx_id] = config[:nsx_id]
1049
- import_opts[:nsx_vni] = config[:nsx_vni]
1050
- import_opts[:nsx_tz_id] = config[:nsx_tz_id]
1051
- end
1052
-
1053
- if vid
1054
- vlanid = VCenterDriver::Network.vlanid(vid)
1055
-
1056
- # we have vlan id
1057
- if /\A\d+\z/.match(vlanid)
1058
- import_opts[:vlanid] = vlanid
1059
- end
1060
- end
1061
-
1062
- # Prepare the Virtual Network template
1063
- one_vnet = VCenterDriver::Network.to_one_template(import_opts)
1064
-
1065
- # always has to be created because of
1066
- # templates when they are instantiated
1067
- ar_tmp = ''
1068
- ar_tmp << "AR=[\n"
1069
- ar_tmp << "TYPE=\"ETHER\",\n"
1070
- ar_tmp << "SIZE=255\n"
1071
- ar_tmp << "]\n"
1072
-
1073
- if vm?
1074
- ar_tmp << create_ar(nic, false, nic[:ipv4]) if nic[:ipv4]
1075
-
1076
- if nic[:ipv6]
1077
- ar_tmp << create_ar(nic, false, nil, nic[:ipv6])
1078
- end
1079
-
1080
- ar_tmp << create_ar(nic, true) if !nic[:ipv4] && !nic[:ipv6]
1081
- end
1082
-
1083
- one_vnet[:one] << ar_tmp
1084
- config[:one_object] = one_vnet[:one]
1085
- _cluster_id = VCenterDriver::VIHelper
1086
- .get_cluster_id(config[:one_ids])
1087
-
1088
- one_vn = VCenterDriver::Network.create_one_network(config)
1089
- VCenterDriver::VIHelper.clean_ref_hash
1090
- one_vn.info
1091
-
1092
- # Wait until the virtual network is in ready state
1093
- t_start = Time.now
1094
- error = false
1095
- timeout = 30
1096
-
1097
- while Time.now - t_start < timeout
1098
- begin
1099
- if one_vn.short_state_str == 'rdy'
1100
- error = false
1101
- break
1102
- end
1103
- rescue StandardError
1104
- error = true
1105
- end
1106
-
1107
- sleep 1
1108
- one_vn.info
1109
- end
1110
-
1111
- if error
1112
- error_msg = "VNET #{one_vn.id} in state "
1113
- error_msg += "#{one_vn.short_state_str}, aborting import"
1114
- raise error_msg
1115
- end
1116
-
1117
- one_vn
1118
- end
1119
-
1120
- def import_vcenter_nics(opts, vm_id = nil, dc_name = nil)
1121
- vi_client = opts[:vi_client]
1122
- vc_uuid = opts[:vc_uuid]
1123
- npool = opts[:npool]
1124
- hpool = opts[:hpool]
1125
- vcenter_instance_name = opts[:vcenter]
1126
- template_ref = opts[:template_moref]
1127
- vm_object = opts[:vm_object]
1128
-
1129
- nic_info = ''
1130
- error = ''
1131
- ar_ids = {}
1132
- begin
1133
- # Lock import operation, to avoid
1134
- # concurrent creation of networks
1135
- lock
1136
-
1137
- if !dc_name
1138
- dc = datacenter
1139
- dc_name = dc.item.name
1140
- dc_ref = dc.item._ref
1141
- end
1142
-
1143
- ccr_ref = self['runtime.host.parent._ref']
1144
- ccr_name = self['runtime.host.parent.name']
1145
-
1146
- # Get nics and info required
1147
- vc_nics = vcenter_nics_hash
1148
-
1149
- # Track allocated networks for rollback
1150
- allocated_networks = []
1151
-
1152
- nic_index = 0
1153
-
1154
- vc_nics.each do |nic|
1155
- [:ipv4, :ipv6].each do |type|
1156
- if nic[type]
1157
- opts[type].shift if opts[type]
1158
- next
1159
- end
1160
-
1161
- begin
1162
- ip = opts[type].shift if opts[type]
1163
-
1164
- # Check if it is a valid IP
1165
- IPAddr.new(ip)
1166
-
1167
- nic[type] = ip
1168
- rescue StandardError
1169
- end
1170
- end
1171
-
1172
- # Check if the network already exists
1173
- network_found =
1174
- VCenterDriver::VIHelper
1175
- .find_by_ref(
1176
- OpenNebula::VirtualNetworkPool,
1177
- 'TEMPLATE/VCENTER_NET_REF',
1178
- nic[:net_ref],
1179
- vc_uuid,
1180
- npool
1181
- )
1182
- # Network is already in OpenNebula
1183
- if network_found
1184
- nic_info << nic_from_network_found(network_found,
1185
- vm_object,
1186
- nic,
1187
- ar_ids,
1188
- nic_index.to_s)
1189
- # Network not found
1190
- else
1191
- opts = {
1192
- :nic => nic,
1193
- :ccr_ref => ccr_ref,
1194
- :ccr_name => ccr_name,
1195
- :vc_uuid => vc_uuid,
1196
- :vcenter_instance_name => vcenter_instance_name,
1197
- :dc_name => dc_name,
1198
- :template_ref => template_ref,
1199
- :dc_ref => dc_ref,
1200
- :vm_id => vm_id,
1201
- :hpool => hpool,
1202
- :vi_client => vi_client
1203
- }
1204
-
1205
- one_vn = create_network_for_import(
1206
- opts
1207
- )
1208
-
1209
- allocated_networks << one_vn
1210
-
1211
- nic_info << nic_from_network_created(
1212
- one_vn,
1213
- nic,
1214
- nic_index.to_s,
1215
- vm_object,
1216
- ar_ids
1217
- )
1218
-
1219
- # Refresh npool
1220
- npool.info_all
1221
- end
1222
- nic_index += 1
1223
- end
1224
- rescue StandardError => e
1225
- error = "\n There was an error trying to create \
1226
- a virtual network to repesent a \
1227
- vCenter network for a VM or VM Template. \
1228
- Reason: #{e.message}"
1229
- ensure
1230
- unlock
1231
- # Rollback, delete virtual networks
1232
- if !error.empty? && allocated_networks
1233
- allocated_networks.each do |n|
1234
- n.delete
1235
- end
1236
- end
1237
- end
1238
-
1239
- [error, nic_info, ar_ids, allocated_networks]
1240
- end
1241
-
1242
- def get_vcenter_disk_key(unit_number, controller_key)
1243
- key = nil
1244
-
1245
- @item['config.hardware.device'].each do |device|
1246
- disk = {}
1247
-
1248
- next unless disk_or_iso?(device)
1249
-
1250
- disk[:device] = device
1251
- next unless device.controllerKey == controller_key &&
1252
- device.unitNumber == unit_number
1253
-
1254
- key = device.key
1255
- break
1256
- end
1257
-
1258
- key
1259
- end
1260
-
1261
- def vcenter_disks_get
1262
- disks = []
1263
- ide_controlled = []
1264
- sata_controlled = []
1265
- scsi_controlled = []
1266
- controller = {}
1267
-
1268
- @item['config.hardware.device'].each do |device|
1269
- disk = {}
1270
-
1271
- if device.is_a? RbVmomi::VIM::VirtualIDEController
1272
- ide_controlled.concat(device.device)
1273
- controller[device.key] = "ide#{device.busNumber}"
1274
- end
1275
-
1276
- if device.is_a? RbVmomi::VIM::VirtualSATAController
1277
- sata_controlled.concat(device.device)
1278
- controller[device.key] = "sata#{device.busNumber}"
1279
- end
1280
-
1281
- if device.is_a? RbVmomi::VIM::VirtualSCSIController
1282
- scsi_controlled.concat(device.device)
1283
- controller[device.key] = "scsi#{device.busNumber}"
1284
- end
1285
-
1286
- next unless disk_or_iso?(device)
1287
-
1288
- disk[:device] = device
1289
-
1290
- unless device.backing.datastore
1291
- raise "datastore not found for VM's device"
1292
- end
1293
-
1294
- disk[:datastore] =
1295
- device.backing.datastore
1296
- disk[:path] =
1297
- device.backing.fileName
1298
- disk[:path_wo_ds]=
1299
- disk[:path].sub(/^\[(.*?)\] /, '')
1300
- disk?(device) ? disk[:type] = 'OS' : disk[:type] = 'CDROM'
1301
- disk[:key] =
1302
- device.key
1303
- if ide_controlled.include?(device.key)
1304
- disk[:prefix] = 'hd'
1305
- end
1306
- if scsi_controlled.include?(device.key)
1307
- disk[:prefix] = 'sd'
1308
- end
1309
- if sata_controlled.include?(device.key)
1310
- disk[:prefix] = 'sd'
1311
- end
1312
- disk[:tag] =
1313
- "#{controller[device.controllerKey]}:#{device.unitNumber}"
1314
-
1315
- disks << disk
1316
- end
1317
-
1318
- disks
1319
- end
1320
-
1321
- def vcenter_nics_list
1322
- nics = []
1323
- @item.config.hardware.device.each do |device|
1324
- nics << device if VCenterDriver::Network.nic?(device)
1325
- end
1326
-
1327
- nics
1328
- end
1329
-
1330
- def identify_network(identifier, network)
1331
- if network.class == RbVmomi::VIM::DistributedVirtualPortgroup
1332
- return network if identifier == network.key
1333
-
1334
- return
1335
- end
1336
-
1337
- if network.class == RbVmomi::VIM::Network
1338
- return network if identifier == network
1339
-
1340
- return
1341
- end
1342
-
1343
- return unless network.class == RbVmomi::VIM::OpaqueNetwork
1344
-
1345
- if identifier == network.summary.opaqueNetworkId
1346
- network
1347
- else
1348
- nil
1349
- end
1350
- end
1351
-
1352
- def retrieve_from_device(device)
1353
- device_network = nil
1354
- device_network_id = nil
1355
- # First search network corresponding this device
1356
- # Distributed Networks and NSX-V Networks
1357
- if !device.backing[:port].nil?
1358
- device_network_id = device.backing.port.portgroupKey
1359
- # Standard Networks
1360
- elsif !device.backing[:network].nil?
1361
- device_network_id = device.backing[:network]
1362
- # NSX-T Opaque Networks
1363
- elsif !device.backing[:opaqueNetworkId].nil?
1364
- device_network_id = device.backing[:opaqueNetworkId]
1365
- end
1366
-
1367
- # Check if networkId exists
1368
- if device_network_id.nil?
1369
- raise "Invalid or not supported network #{device.backing}"
1370
- end
1371
-
1372
- # Matching between device and network objects
1373
- @item.network.each do |net|
1374
- device_network = identify_network(device_network_id, net)
1375
- break unless device_network.nil?
1376
- end
1377
-
1378
- # Check network matching
1379
- if device_network.nil?
1380
- raise "\"#{device.deviceInfo.label}\" \
1381
- not match any known network"
1382
- end
1383
-
1384
- res = {}
1385
-
1386
- res[:refs] = device_network.host.map do |h|
1387
- h.parent._ref if h.parent
1388
- end
1389
-
1390
- res[:net_name] =
1391
- device_network.name
1392
- res[:net_ref] =
1393
- device_network._ref
1394
- res[:pg_type] =
1395
- VCenterDriver::Network
1396
- .get_network_type(
1397
- device_network,
1398
- res[:net_name]
1399
- )
1400
- res[:network] =
1401
- device_network
1402
-
1403
- res
1404
- end
1405
-
1406
- def vcenter_nics_hash
1407
- parse_live = lambda {|inets_raw|
1408
- h = nil
1409
- begin
1410
- h = inets_raw.to_h
1411
- rescue NoMethodError
1412
- h = {}
1413
- inets_raw.each do |nic_dev|
1414
- h[nic_dev[0]] = nic_dev[1]
1415
- end
1416
- end
1417
-
1418
- return h
1419
- }
1420
-
1421
- nics = []
1422
- inets_raw = nil
1423
- inets = {}
1424
-
1425
- @item['config.hardware.device'].each do |device|
1426
- next unless VCenterDriver::Network.nic?(device)
1427
-
1428
- nic = retrieve_from_device(device)
1429
- nic[:mac] = device.macAddress rescue nil
1430
-
1431
- if vm? && online?
1432
- inets_raw ||=
1433
- @item['guest.net']
1434
- .map
1435
- .with_index {|x, _| [x.macAddress, x] }
1436
- inets = parse_live.call(inets_raw) if inets.empty?
1437
-
1438
- if !inets[nic[:mac]].nil?
1439
- ip_addresses =
1440
- inets[nic[:mac]]
1441
- .ipConfig
1442
- .ipAddress rescue nil
1443
- end
1444
-
1445
- if !ip_addresses.nil? && !ip_addresses.empty?
1446
- nic[:ipv4],
1447
- nic[:ipv4_additionals] = nil
1448
- nic[:ipv6],
1449
- nic[:ipv6_ula],
1450
- nic[:ipv6_global],
1451
- nic[:ipv6_additionals] = nil
1452
- fill_nic(ip_addresses, nic)
1453
- end
1454
- end
1455
- nics << nic
1456
- end
1457
-
1458
- nics
1459
- end
1460
-
1461
- def fill_nic(ip_addresses, nic)
1462
- (0...ip_addresses.length).each do |i|
1463
- ip = ip_addresses[i].ipAddress
1464
- if ip =~ Resolv::IPv4::Regex
1465
- if nic[:ipv4]
1466
- if nic[:ipv4_additionals]
1467
- nic[:ipv4_additionals] += ',' + ip
1468
- else
1469
- nic[:ipv4_additionals] = ip
1470
- end
1471
- else
1472
- nic[:ipv4] = ip
1473
- end
1474
- elsif ip_addresses[i].ipAddress =~ Resolv::IPv6::Regex
1475
- if get_ipv6_prefix(ip, 10) == 'fe80'
1476
- # we not process this address
1477
- elsif get_ipv6_prefix(ip, 7) == 'fc00'
1478
- nic[:ipv6_ula] = ip
1479
- else
1480
- if nic[:ipv6]
1481
- if nic[:ipv6_additionals]
1482
- nic[:ipv6_additionals] += ',' + ip
1483
- else
1484
- nic[:ipv6_additionals] = ip
1485
- end
1486
- else
1487
- nic[:ipv6] = ip
1488
- end
1489
- end
1490
- end
1491
- end
1492
- end
1493
-
1494
- def get_ipv6_prefix(ipv6, prefix_length)
1495
- ip_slice =
1496
- ipv6
1497
- .split(':')
1498
- .map {|elem| elem.hex }
1499
- .map do |elem|
1500
- int, dec = elem.divmod(1)
1501
- bin = int.to_s(2).to_s
1502
-
1503
- while dec > 0
1504
- int, dec = (dec * 2).divmod(1)
1505
- bin << int.to_s
1506
- end
1507
-
1508
- bin
1509
- end.map {|elem| elem.rjust(16, '0') } # rubocop:disable Style/MultilineBlockChain
1510
-
1511
- ip_chain = ip_slice.join
1512
- prefix = ip_chain[0, prefix_length]
1513
-
1514
- cont = 0
1515
- limit = prefix.length
1516
- index = 0
1517
- slices = []
1518
-
1519
- while cont < limit
1520
- slices[index] = prefix.slice(cont, 4)
1521
- slices[index] = slices[index].ljust(4, '0')
1522
- index +=1
1523
- cont+=4
1524
- end
1525
-
1526
- slices.map {|elem| format('%0x', elem.to_i(2)) }
1527
- .join.ljust(4, '0')
1528
- end
1529
-
1530
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk or a cdrom
1531
- def disk_or_cdrom?(device)
1532
- is_disk =
1533
- !device
1534
- .class
1535
- .ancestors
1536
- .index(RbVmomi::VIM::VirtualDisk).nil?
1537
- is_cdrom =
1538
- !device
1539
- .class
1540
- .ancestors
1541
- .index(RbVmomi::VIM::VirtualCdrom).nil?
1542
- is_disk || is_cdrom
1543
- end
1544
-
1545
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk or an iso file
1546
- def disk_or_iso?(device)
1547
- is_disk =
1548
- !device
1549
- .class
1550
- .ancestors
1551
- .index(RbVmomi::VIM::VirtualDisk).nil?
1552
- is_iso =
1553
- device
1554
- .backing
1555
- .is_a? RbVmomi::VIM::VirtualCdromIsoBackingInfo
1556
- is_disk || is_iso
1557
- end
1558
-
1559
- # Checks if a RbVmomi::VIM::VirtualDevice is a disk
1560
- def disk?(device)
1561
- !device.class.ancestors.index(RbVmomi::VIM::VirtualDisk).nil?
1562
- end
1563
-
1564
- def cdrom?(device)
1565
- device.backing.is_a? RbVmomi::VIM::VirtualCdromIsoBackingInfo
1566
- end
1567
-
1568
- # @return RbVmomi::VIM::ResourcePool, first resource pool in cluster
1569
- def resource_pool
1570
- self['runtime.host.parent.resourcePool']
1571
- end
1572
-
1573
- def esx_name
1574
- self['runtime.host.name']
1575
- end
1576
-
1577
- def vm_to_one(vm_name)
1578
- str = "NAME = \"#{vm_name}\"\n"\
1579
- "CPU = \"#{@vm_info['config.hardware.numCPU']}\"\n"\
1580
- "vCPU = \"#{@vm_info['config.hardware.numCPU']}\"\n"\
1581
- "MEMORY = \"#{@vm_info['config.hardware.memoryMB']}\"\n"\
1582
- "HYPERVISOR = \"vcenter\"\n"\
1583
- "CONTEXT = [\n"\
1584
- " NETWORK = \"YES\",\n"\
1585
- " SSH_PUBLIC_KEY = \"$USER[SSH_PUBLIC_KEY]\"\n"\
1586
- "]\n"\
1587
- "VCENTER_INSTANCE_ID =\"#{@vm_info[:vc_uuid]}\"\n"\
1588
- "VCENTER_CCR_REF =\"#{@vm_info[:cluster_ref]}\"\n"
1589
-
1590
- str << "DEPLOY_ID =\"#{self['_ref']}\"\n"
1591
- @state = 'POWEROFF' if @state == 'd'
1592
- str << "IMPORT_STATE =\"#{@state}\"\n"
1593
-
1594
- # Get DS information
1595
- if !@vm_info['datastore'].nil?
1596
- !@vm_info['datastore'].last.nil? &&
1597
- !@vm_info['datastore'].last._ref.nil?
1598
- ds_ref = vm_template_ds_ref
1599
- str << "VCENTER_DS_REF = \"#{ds_ref}\"\n"
1600
- end
1601
-
1602
- vnc_port = nil
1603
- keymap =
1604
- VCenterDriver::VIHelper
1605
- .get_default(
1606
- 'VM/TEMPLATE/GRAPHICS/KEYMAP'
1607
- )
1608
-
1609
- @vm_info['config.extraConfig'].select do |xtra|
1610
- if xtra[:key].downcase=='remotedisplay.vnc.port'
1611
- vnc_port = xtra[:value]
1612
- end
1613
-
1614
- if xtra[:key].downcase=='remotedisplay.vnc.keymap'
1615
- keymap = xtra[:value]
1616
- end
1617
- end
1618
-
1619
- if !@vm_info['config.extraConfig'].empty?
1620
- str << "GRAPHICS = [\n"\
1621
- " TYPE =\"vnc\",\n"
1622
- str << " PORT =\"#{vnc_port}\",\n" if vnc_port
1623
- str << " KEYMAP =\"#{keymap}\",\n" if keymap
1624
- str << " LISTEN =\"0.0.0.0\"\n"
1625
- str << "]\n"
1626
- end
1627
-
1628
- if !@vm_info['config.annotation'] || @vm_info['config.annotation']
1629
- .empty?
1630
- str << 'DESCRIPTION = "vCenter Template \
1631
- imported by OpenNebula' \
1632
- " from Cluster #{@vm_info['cluster_name']}\"\n"
1633
- else
1634
- notes = @vm_info['config.annotation']
1635
- .gsub('\\', '\\\\')
1636
- .gsub('"', '\\"')
1637
- str << "DESCRIPTION = \"#{notes}\"\n"
1638
- end
1639
-
1640
- case @vm_info['guest.guestFullName']
1641
- when /CentOS/i
1642
- str << "LOGO=images/logos/centos.png\n"
1643
- when /Debian/i
1644
- str << "LOGO=images/logos/debian.png\n"
1645
- when /Red Hat/i
1646
- str << "LOGO=images/logos/redhat.png\n"
1647
- when /Ubuntu/i
1648
- str << "LOGO=images/logos/ubuntu.png\n"
1649
- when /Windows XP/i
1650
- str << "LOGO=images/logos/windowsxp.png\n"
1651
- when /Windows/i
1652
- str << "LOGO=images/logos/windows8.png\n"
1653
- when /Linux/i
1654
- str << "LOGO=images/logos/linux.png\n"
1655
- end
1656
-
1657
- str
1658
- end
1659
-
1660
- # Gets MOREF from Datastore used by the VM. It validates
1661
- # the selected DS is not only used to host swap.
1662
- def vm_template_ds_ref
1663
- begin
1664
- ds_ref = nil
1665
- if @vm_info['datastore'].length > 1
1666
- swap_path = ''
1667
- @vm_info['config.extraConfig'].each do |element|
1668
- if element.key == 'sched.swap.derivedName'
1669
- swap_path = element.value
1670
- end
1671
- end
1672
- @vm_info['datastore'].each do |datastore|
1673
- path = datastore.summary.url.sub(%r{ds:///*}, '')
1674
- if !swap_path.include?(path) && !datastore._ref.nil?
1675
- ds_ref = datastore._ref
1676
- break
1677
- end
1678
- end
1679
- elsif @vm_info['datastore'].length == 1
1680
- if !@vm_info['datastore'].first._ref.nil?
1681
- ds_ref = @vm_info['datastore'].first._ref
1682
- end
1683
- end
1684
-
1685
- ds_ref
1686
- rescue StandardError => e
1687
- "Could not find DATASTORE for this VM. Reason: #{e.message}"
1688
- end
1689
- end
1690
-
1691
- def self.template_to_one(
1692
- template,
1693
- vc_uuid,
1694
- ccr_ref,
1695
- ccr_name,
1696
- import_name
1697
- )
1698
- num_cpu, memory, annotation, guest_fullname =
1699
- template
1700
- .item
1701
- .collect(
1702
- 'config.hardware.numCPU',
1703
- 'config.hardware.memoryMB',
1704
- 'config.annotation',
1705
- 'guest.guestFullName'
1706
- )
1707
-
1708
- str = "NAME = \"#{import_name}\"\n"\
1709
- "CPU = \"#{num_cpu}\"\n"\
1710
- "vCPU = \"#{num_cpu}\"\n"\
1711
- "MEMORY = \"#{memory}\"\n"\
1712
- "HYPERVISOR = \"vcenter\"\n"\
1713
- "CONTEXT = [\n"\
1714
- " NETWORK = \"YES\",\n"\
1715
- " SSH_PUBLIC_KEY = \"$USER[SSH_PUBLIC_KEY]\"\n"\
1716
- "]\n"\
1717
- "VCENTER_INSTANCE_ID =\"#{vc_uuid}\"\n"
1718
-
1719
- str << "VCENTER_TEMPLATE_REF =\"#{template['_ref']}\"\n"
1720
- str << "VCENTER_CCR_REF =\"#{ccr_ref}\"\n"
1721
-
1722
- str << "GRAPHICS = [\n"\
1723
- " TYPE =\"vnc\",\n"
1724
- str << " LISTEN =\"0.0.0.0\"\n"
1725
- str << "]\n"
1726
-
1727
- if annotation.nil? || annotation.empty?
1728
- str << 'DESCRIPTION = "vCenter Template imported by OpenNebula'\
1729
- " from Cluster #{ccr_name}\"\n"
1730
- else
1731
- notes = annotation.gsub('\\', '\\\\').gsub('"', '\\"')
1732
- str << "DESCRIPTION = \"#{notes}\"\n"
1733
- end
1734
-
1735
- case guest_fullname
1736
- when /CentOS/i
1737
- str << "LOGO=images/logos/centos.png\n"
1738
- when /Debian/i
1739
- str << "LOGO=images/logos/debian.png\n"
1740
- when /Red Hat/i
1741
- str << "LOGO=images/logos/redhat.png\n"
1742
- when /Ubuntu/i
1743
- str << "LOGO=images/logos/ubuntu.png\n"
1744
- when /Windows XP/i
1745
- str << "LOGO=images/logos/windowsxp.png\n"
1746
- when /Windows/i
1747
- str << "LOGO=images/logos/windows8.png\n"
1748
- when /Linux/i
1749
- str << "LOGO=images/logos/linux.png\n"
1750
- end
1751
-
1752
- str
1753
- end
1754
-
1755
- def self.get_xml_template(
1756
- template,
1757
- vcenter_uuid,
1758
- vi_client,
1759
- dc_name = nil,
1760
- rp_cache = {}
1761
- )
1762
- begin
1763
- template_ref = template['_ref']
1764
- template_name = template['name']
1765
- template_ccr = template['runtime.host.parent']
1766
- template_ccr_ref = template_ccr._ref
1767
- template_ccr_name = template_ccr.name
1768
-
1769
- # Get datacenter info
1770
- if !dc_name
1771
- dc = datacenter
1772
- dc_name = dc.item.name
1773
- end
1774
-
1775
- # Get resource pools and generate a list
1776
- if !rp_cache[template_ccr_name]
1777
- tmp_cluster =
1778
- VCenterDriver::ClusterComputeResource
1779
- .new_from_ref(
1780
- template_ccr_ref,
1781
- vi_client
1782
- )
1783
- rp_list = tmp_cluster.get_resource_pool_list
1784
- rp = ''
1785
- if !rp_list.empty?
1786
- rp_name_list = []
1787
- rp_list.each do |rp_hash|
1788
- rp_name_list << rp_hash[:name]
1789
- end
1790
- rp = 'O|list|Which resource pool \
1791
- you want this VM to run in? '
1792
- rp << "|#{rp_name_list.join(',')}" # List of RP
1793
- rp << "|#{rp_name_list.first}" # Default RP
1794
- end
1795
- rp_cache[template_ccr_name] = {}
1796
- rp_cache[template_ccr_name][:rp] = rp
1797
- rp_cache[template_ccr_name][:rp_list] = rp_list
1798
- end
1799
- rp = rp_cache[template_ccr_name][:rp]
1800
- rp_list = rp_cache[template_ccr_name][:rp_list]
1801
-
1802
- # Determine the location path for the template
1803
- vcenter_template =
1804
- VCenterDriver::VirtualMachine
1805
- .new_without_id(
1806
- vi_client,
1807
- template_ref
1808
- )
1809
- item = vcenter_template.item
1810
- folders = []
1811
- until item.instance_of? RbVmomi::VIM::Datacenter
1812
- item = item.parent
1813
- first_condition =
1814
- !(item.instance_of? RbVmomi::VIM::Datacenter)
1815
- second_condition =
1816
- item.name != 'vm'
1817
-
1818
- if first_condition && second_condition
1819
- folders << item.name
1820
- end
1821
- if item.nil?
1822
- raise 'Could not find the templates parent location'
1823
- end
1824
- end
1825
- location = folders.reverse.join('/')
1826
- location = '/' if location.empty?
1827
-
1828
- # Generate a crypto hash for the template
1829
- # name and take the first 12 chars
1830
- import_name =
1831
- VCenterDriver::VIHelper
1832
- .one_name(
1833
- OpenNebula::TemplatePool,
1834
- template_name,
1835
- template_ref+vcenter_uuid
1836
- )
1837
-
1838
- template_name = template_name.tr("\u007F", '')
1839
- template_ccr_name = template_ccr_name.tr("\u007F", '')
1840
-
1841
- # Prepare the Hash that will be used by importers to display
1842
- # the object being imported
1843
- one_tmp = {}
1844
- one_tmp[:name] = import_name
1845
- one_tmp[:ref] = template_ref
1846
- one_tmp[:dc_name] = dc_name
1847
- one_tmp[:template_name] = template_name
1848
- one_tmp[:sunstone_template_name]=
1849
- "#{template_name} [ Cluster: #{template_ccr_name}" \
1850
- " - Template location: #{location} ]"
1851
- one_tmp[:template_location] = location
1852
- one_tmp[:vcenter_ccr_ref] = template_ccr_ref
1853
- one_tmp[:vcenter_ref] = template_ref
1854
- one_tmp[:vcenter_instance_uuid] = vcenter_uuid
1855
- one_tmp[:cluster_name] = template_ccr_name
1856
- one_tmp[:rp] = rp
1857
- one_tmp[:rp_list] = rp_list
1858
- one_tmp[:template] = template
1859
- # By default we import disks and nics
1860
- one_tmp[:import_disks_and_nics] = true
1861
-
1862
- # Get the host ID of the OpenNebula host
1863
- # which represents the vCenter Cluster
1864
- one_host =
1865
- VCenterDriver::VIHelper
1866
- .find_by_ref(
1867
- OpenNebula::HostPool,
1868
- 'TEMPLATE/VCENTER_CCR_REF',
1869
- template_ccr_ref,
1870
- vcenter_uuid
1871
- )
1872
- host_id = one_host['ID']
1873
- unless host_id
1874
- raise "Could not find the host's ID associated \
1875
- to template being imported"
1876
- end
1877
-
1878
- # Get the OpenNebula's template hash
1879
- one_tmp[:one] =
1880
- template_to_one(
1881
- template,
1882
- vcenter_uuid,
1883
- template_ccr_ref,
1884
- template_ccr_name,
1885
- import_name
1886
- )
1887
- one_tmp
1888
- rescue StandardError
1889
- nil
1890
- end
1891
- end
1892
-
1893
- # TODO: check with uuid
1894
- def self.new_from_ref(ref, vi_client)
1895
- new(RbVmomi::VIM::VirtualMachine.new(vi_client.vim, ref), vi_client)
1896
- end
1897
-
1898
- end
1899
-
1900
- ##########################################################################
1901
- # Class VmImporter
1902
- ##########################################################################
1903
- class VmImporter < VCenterDriver::VcImporter
1904
-
1905
- def initialize(one_client, vi_client)
1906
- super(one_client, vi_client)
1907
- @one_class = OpenNebula::Template
1908
-
1909
- @defaults = {
1910
- :linked_clone => '0',
1911
- :copy => '0',
1912
- :name => '',
1913
- :folder => '',
1914
- :resourcepool => [],
1915
- :type => ''
1916
- }
1917
- end
1918
-
1919
- def get_list(_args = {})
1920
- dc_folder = VCenterDriver::DatacenterFolder.new(@vi_client)
1921
-
1922
- # Get OpenNebula's templates pool
1923
- tpool =
1924
- VCenterDriver::VIHelper
1925
- .one_pool(
1926
- OpenNebula::TemplatePool,
1927
- false
1928
- )
1929
- if tpool.respond_to?(:message)
1930
- raise "Could not get OpenNebula TemplatePool: #{tpool.message}"
1931
- end
1932
-
1933
- @list = dc_folder.get_unimported_templates(@vi_client, tpool)
1934
- end
1935
-
1936
- def rp_opts(type, rps)
1937
- str = ''
1938
-
1939
- return str if (type == 'default') || rps.empty?
1940
-
1941
- if type == 'fixed'
1942
- str << "VCENTER_RESOURCE_POOL=\"#{rps}\"\n"
1943
- else
1944
- default = rps.first
1945
- rps_str = rps.join(',')
1946
-
1947
- str << 'USER_INPUTS=['
1948
- str << "VCENTER_RESOURCE_POOL=\"M|list|resource \
1949
- pool list|#{rps_str}|#{default}\""
1950
- str << ']'
1951
- end
1952
-
1953
- str
1954
- end
1955
-
1956
- def import(selected)
1957
- opts = @info[selected[:ref]][:opts]
1958
- working_template = selected
1959
-
1960
- vcenter = selected[:vcenter]
1961
- vc_uuid = selected[:vcenter_instance_uuid]
1962
- dc = selected[:dc_name]
1963
-
1964
- linked_clone = opts[:linked_clone] == '1'
1965
- copy = opts[:copy] == '1'
1966
- deploy_in_folder = !opts[:folder].empty?
1967
-
1968
- res = { :id => [], :name => selected[:name] }
1969
- dpool, ipool, npool, hpool = create_pools
1970
-
1971
- template =
1972
- VCenterDriver::Template
1973
- .new_from_ref(
1974
- selected[:vcenter_ref],
1975
- @vi_client
1976
- )
1977
- # Linked clones and copy preparation
1978
- if linked_clone
1979
- # reached this point we need to delete
1980
- # the template if something go wrong
1981
- if copy
1982
- error, template_copy_ref =
1983
- selected[:template].save_as_linked_clones(opts[:name])
1984
-
1985
- unless template_copy_ref
1986
- raise 'There is a problem creating ' \
1987
- "your copy: #{error}"
1988
- end
1989
-
1990
- template =
1991
- VCenterDriver::Template
1992
- .new_from_ref(
1993
- template_copy_ref,
1994
- @vi_client
1995
- )
1996
- @rollback <<
1997
- Raction
1998
- .new(
1999
- template,
2000
- :delete_template
2001
- )
2002
-
2003
- one_template =
2004
- VCenterDriver::Template
2005
- .get_xml_template(
2006
- template,
2007
- vc_uuid,
2008
- @vi_client,
2009
- dc
2010
- )
2011
- unless one_template
2012
- raise 'There is a problem obtaining info '\
2013
- "from your template's copy"
2014
- end
2015
-
2016
- working_template = one_template
2017
- end
2018
-
2019
- lc_error, use_lc = template.create_delta_disks
2020
- if lc_error
2021
- raise 'Something was wront with create \
2022
- delta disk operation'
2023
- end
2024
-
2025
- if use_lc
2026
- working_template[:one] <<
2027
- "\nVCENTER_LINKED_CLONES=\"YES\"\n"
2028
- end
2029
- end
2030
-
2031
- if deploy_in_folder
2032
- working_template[:one] <<
2033
- "VCENTER_VM_FOLDER=\"#{opts[:folder]}\"\n"
2034
- end
2035
-
2036
- working_template[:one] <<
2037
- "VCENTER_TEMPLATE_NAME=\"#{selected[:name]}\"\n"
2038
-
2039
- unless copy
2040
- create(working_template[:one]) do |one_object, id|
2041
- res[:id] << id
2042
-
2043
- type = { :object => 'template', :id => id }
2044
- error, template_disks, allocated_images =
2045
- template
2046
- .import_vcenter_disks(
2047
- vc_uuid,
2048
- dpool,
2049
- ipool,
2050
- type
2051
- )
2052
-
2053
- if allocated_images
2054
- # rollback stack
2055
- allocated_images.reverse.each do |i|
2056
- @rollback.unshift(Raction.new(i, :delete))
2057
- end
2058
- end
2059
- raise error unless error.empty?
2060
-
2061
- working_template[:one] << template_disks
2062
-
2063
- if template_copy_ref
2064
- template_moref = template_copy_ref
2065
- else
2066
- template_moref = selected[:vcenter_ref]
2067
- end
2068
-
2069
- opts_nics = {
2070
- :vi_client => @vi_client,
2071
- :vc_uuid => vc_uuid,
2072
- :npool => npool,
2073
- :hpool => hpool,
2074
- :vcenter => vcenter,
2075
- :template_moref => template_moref,
2076
- :vm_object => nil
2077
- }
2078
-
2079
- error, template_nics, _ar_ids, allocated_nets =
2080
- template
2081
- .import_vcenter_nics(
2082
- opts_nics,
2083
- id,
2084
- dc
2085
- )
2086
-
2087
- if allocated_nets
2088
- # rollback stack
2089
- allocated_nets.reverse.each do |n|
2090
- @rollback.unshift(Raction.new(n, :delete))
2091
- end
2092
- end
2093
- raise error unless error.empty?
2094
-
2095
- working_template[:one] << template_nics
2096
- working_template[:one] << rp_opts(
2097
- opts[:type],
2098
- opts[:resourcepool]
2099
- )
2100
-
2101
- one_object.update(working_template[:one])
2102
- end
2103
- end
2104
-
2105
- res
2106
- end
2107
-
2108
- def attr
2109
- 'TEMPLATE/VCENTER_TEMPLATE_REF'
2110
- end
2111
-
2112
- end
2113
-
2114
- end