opennebula 6.10.5 → 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 +354 -98
  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 -1522
  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 -3573
  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/host.rb DELETED
@@ -1,1522 +0,0 @@
1
- # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2024, OpenNebula Project, OpenNebula Systems #
3
- # #
4
- # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
- # not use this file except in compliance with the License. You may obtain #
6
- # a copy of the License at #
7
- # #
8
- # http://www.apache.org/licenses/LICENSE-2.0 #
9
- # #
10
- # Unless required by applicable law or agreed to in writing, software #
11
- # distributed under the License is distributed on an "AS IS" BASIS, #
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
- # See the License for the specific language governing permissions and #
14
- # limitations under the License. #
15
- #--------------------------------------------------------------------------- #
16
-
17
- ##############################################################################
18
- # Module VCenterDriver
19
- ##############################################################################
20
- module VCenterDriver
21
-
22
- require 'json'
23
- require 'nsx_driver'
24
-
25
- ##########################################################################
26
- # Class HostFolder
27
- ##########################################################################
28
- class HostFolder
29
-
30
- attr_accessor :item, :items
31
-
32
- def initialize(item)
33
- @item = item
34
- @items = {}
35
- end
36
-
37
- def fetch_clusters!
38
- VIClient
39
- .get_entities(
40
- @item,
41
- 'ClusterComputeResource'
42
- ).each do |item|
43
- item_name = item._ref
44
- @items[item_name.to_sym] = ClusterComputeResource.new(item)
45
- end
46
- end
47
-
48
- def get_cluster(ref)
49
- if !@items[ref.to_sym]
50
- rbvmomi_dc =
51
- RbVmomi::VIM::ClusterComputeResource
52
- .new(
53
- @item._connection,
54
- ref
55
- )
56
- @items[ref.to_sym] =
57
- ClusterComputeResource
58
- .new(
59
- rbvmomi_dc
60
- )
61
- end
62
-
63
- @items[ref.to_sym]
64
- end
65
-
66
- end
67
- # class HostFolder
68
-
69
- ##########################################################################
70
- # Class ClusterComputeResource
71
- ##########################################################################
72
- class ClusterComputeResource
73
-
74
- attr_accessor :item
75
- attr_accessor :rp_list
76
-
77
- include Memoize
78
-
79
- def initialize(item, vi_client = nil)
80
- @item = item
81
- @vi_client = vi_client
82
- @rp_list # rubocop:disable Lint/Void
83
- end
84
-
85
- def fetch_resource_pools(rp, rp_array = [])
86
- rp_array << rp
87
-
88
- rp.resourcePool.each do |child_rp|
89
- fetch_resource_pools(child_rp, rp_array)
90
- end
91
-
92
- rp_array
93
- end
94
-
95
- def resource_pools
96
- if @resource_pools.nil?
97
- @resource_pools = fetch_resource_pools(@item.resourcePool)
98
- end
99
-
100
- @resource_pools
101
- end
102
-
103
- def get_resource_pool_list(
104
- rp = @item
105
- .resourcePool,
106
- parent_prefix = '',
107
- rp_array = []
108
- )
109
- current_rp = ''
110
-
111
- if !parent_prefix.empty?
112
- current_rp << parent_prefix
113
- current_rp << '/'
114
- end
115
-
116
- resource_pool, name = rp.collect('resourcePool', 'name')
117
- current_rp << name if name != 'Resources'
118
-
119
- resource_pool.each do |child_rp|
120
- get_resource_pool_list(child_rp, current_rp, rp_array)
121
- end
122
-
123
- rp_info = {}
124
- rp_info[:name] = current_rp
125
- rp_info[:ref] = rp._ref
126
- rp_array << rp_info unless current_rp.empty?
127
-
128
- rp_array
129
- end
130
-
131
- def nsx_get
132
- nsx_info = ''
133
- nsx_obj = {}
134
- # In the future add more than one nsx manager
135
- extension_list =
136
- @vi_client
137
- .vim
138
- .serviceContent
139
- .extensionManager
140
- .extensionList
141
- extension_list.each do |ext_list|
142
- case ext_list.key
143
- when NSXDriver::NSXConstants::NSXV_EXTENSION_LIST
144
- nsx_obj['type'] = NSXDriver::NSXConstants::NSXV
145
- url_full = ext_list.client[0].url
146
- url_split = url_full.split('/')
147
- # protocol = "https://"
148
- protocol = url_split[0] + '//'
149
- # ip_port = ip:port
150
- ip_port = url_split[2]
151
- nsx_obj['url'] = protocol + ip_port
152
- nsx_obj['version'] = ext_list.version
153
- nsx_obj['label'] = ext_list.description.label
154
- when NSXDriver::NSXConstants::NSXT_EXTENSION_LIST
155
- nsx_obj['type'] = NSXDriver::NSXConstants::NSXT
156
- nsx_obj['url'] = ext_list.server[0].url
157
- nsx_obj['version'] = ext_list.version
158
- nsx_obj['label'] = ext_list.description.label
159
- else
160
- next
161
- end
162
- end
163
- unless nsx_obj.empty?
164
- nsx_info << "NSX_MANAGER=\"#{nsx_obj['url']}\"\n"
165
- nsx_info << "NSX_TYPE=\"#{nsx_obj['type']}\"\n"
166
- nsx_info << "NSX_VERSION=\"#{nsx_obj['version']}\"\n"
167
- nsx_info << "NSX_LABEL=\"#{nsx_obj['label']}\"\n"
168
- end
169
- nsx_info
170
- end
171
-
172
- def nsx_ready?
173
- @one_item =
174
- VCenterDriver::VIHelper
175
- .one_item(
176
- OpenNebula::Host,
177
- @vi_client
178
- .instance_variable_get(
179
- :@host_id
180
- ).to_i
181
- )
182
-
183
- # Check if NSX_MANAGER is into the host template
184
- if [nil, ''].include?(@one_item['TEMPLATE/NSX_MANAGER'])
185
- @nsx_status = "NSX_STATUS = \"Missing NSX_MANAGER\"\n"
186
- return false
187
- end
188
-
189
- # Check if NSX_USER is into the host template
190
- if [nil, ''].include?(@one_item['TEMPLATE/NSX_USER'])
191
- @nsx_status = "NSX_STATUS = \"Missing NSX_USER\"\n"
192
- return false
193
- end
194
-
195
- # Check if NSX_PASSWORD is into the host template
196
- if [nil, ''].include?(@one_item['TEMPLATE/NSX_PASSWORD'])
197
- @nsx_status = "NSX_STATUS = \"Missing NSX_PASSWORD\"\n"
198
- return false
199
- end
200
-
201
- # Check if NSX_TYPE is into the host template
202
- if [nil, ''].include?(@one_item['TEMPLATE/NSX_TYPE'])
203
- @nsx_status = "NSX_STATUS = \"Missing NSX_TYPE\"\n"
204
- return false
205
- end
206
-
207
- # Try a connection as part of NSX_STATUS
208
- nsx_client = NSXDriver::NSXClient
209
- .new_from_id(
210
- @vi_client
211
- .instance_variable_get(
212
- :@host_id
213
- ).to_i
214
- )
215
-
216
- if @one_item['TEMPLATE/NSX_TYPE'] == NSXDriver::NSXConstants::NSXV
217
- # URL to test a connection
218
- url = '/api/2.0/vdn/scopes'
219
- begin
220
- if nsx_client.get(url)
221
- @nsx_status = "NSX_STATUS = \"OK\"\n"
222
- return true
223
- else
224
- @nsx_status =
225
- "NSX_STATUS = \"Response code incorrect\"\n"
226
- return false
227
- end
228
- rescue StandardError
229
- @nsx_status = 'NSX_STATUS = "Error connecting to ' \
230
- "NSX_MANAGER\"\n"
231
- return false
232
- end
233
- end
234
-
235
- nxs_type = @one_item['TEMPLATE/NSX_TYPE']
236
- return unless nxs_type == NSXDriver::NSXConstants::NSXT
237
-
238
- # URL to test a connection
239
- url = '/api/v1/transport-zones'
240
- begin
241
- if nsx_client.get(url)
242
- @nsx_status = "NSX_STATUS = \"OK\"\n"
243
- true
244
- else
245
- @nsx_status =
246
- "NSX_STATUS = \"Response code incorrect\"\n"
247
- false
248
- end
249
- rescue StandardError
250
- @nsx_status = 'NSX_STATUS = "Error connecting to '\
251
- "NSX_MANAGER\"\n"
252
- false
253
- end
254
- end
255
-
256
- def tz_get
257
- @nsx_status = ''
258
- if !nsx_ready?
259
- tz_info = @nsx_status
260
- else
261
- tz_info = "NSX_STATUS = OK\n"
262
- tz_info << 'NSX_TRANSPORT_ZONES = ['
263
-
264
- nsx_client =
265
- NSXDriver::NSXClient
266
- .new_from_id(
267
- @vi_client
268
- .instance_variable_get(
269
- :@host_id
270
- ).to_i
271
- )
272
- tz_object = NSXDriver::TransportZone.new_child(nsx_client)
273
-
274
- # NSX request to get Transport Zones
275
- case @one_item['TEMPLATE/NSX_TYPE']
276
- when NSXDriver::NSXConstants::NSXV
277
- tzs = tz_object.tzs
278
- tzs.each do |tz|
279
- tz_info << tz.xpath('name').text << '="'
280
- tz_info << tz.xpath('objectId').text << '",'
281
- end
282
- tz_info.chomp!(',')
283
- when NSXDriver::NSXConstants::NSXT
284
- r = tz_object.tzs
285
- r['results'].each do |tz|
286
- tz_info << tz['display_name'] << '="'
287
- tz_info << tz['id'] << '",'
288
- end
289
- tz_info.chomp!(',')
290
- else
291
- raise "Unknown Port Group type \
292
- #{@one_item['TEMPLATE/NSX_TYPE']}"
293
- end
294
- tz_info << ']'
295
- return tz_info
296
- end
297
- tz_info
298
- end
299
-
300
- def monitor
301
- total_cpu,
302
- num_cpu_cores,
303
- effective_cpu,
304
- total_memory,
305
- effective_mem,
306
- num_hosts,
307
- num_eff_hosts,
308
- overall_status,
309
- drs_enabled,
310
- ha_enabled= @item.collect('summary.totalCpu',
311
- 'summary.numCpuCores',
312
- 'summary.effectiveCpu',
313
- 'summary.totalMemory',
314
- 'summary.effectiveMemory',
315
- 'summary.numHosts',
316
- 'summary.numEffectiveHosts',
317
- 'summary.overallStatus',
318
- 'configuration.drsConfig.enabled',
319
- 'configuration.dasConfig.enabled')
320
-
321
- mhz_core = total_cpu.to_f / num_cpu_cores.to_f
322
- eff_core = effective_cpu.to_f / mhz_core
323
-
324
- free_cpu = format('%.2f', eff_core * 100).to_f # rubocop:disable Style/FormatStringToken
325
- total_cpu = num_cpu_cores.to_f * 100
326
- used_cpu = format('%.2f', total_cpu - free_cpu).to_f # rubocop:disable Style/FormatStringToken
327
-
328
- total_mem = total_memory.to_i / 1024
329
- free_mem = effective_mem.to_i * 1024
330
-
331
- str_info = ''
332
-
333
- # Get cluster name for informative purposes
334
- # (replace space with _ if any)
335
- str_info << 'VCENTER_NAME=' << self['name'].tr(' ', '_') << "\n"
336
-
337
- # System
338
- str_info << "HYPERVISOR=vcenter\n"
339
- str_info << 'TOTALHOST=' << num_hosts.to_s << "\n"
340
- str_info << 'AVAILHOST=' << num_eff_hosts.to_s << "\n"
341
- str_info << 'STATUS=' << overall_status << "\n"
342
-
343
- # CPU
344
- str_info << 'CPUSPEED=' << mhz_core.to_s << "\n"
345
- str_info << 'TOTALCPU=' << total_cpu.to_s << "\n"
346
- str_info << 'USEDCPU=' << used_cpu.to_s << "\n"
347
- str_info << 'FREECPU=' << free_cpu.to_s << "\n"
348
-
349
- # Memory
350
- str_info << 'TOTALMEMORY=' << total_mem.to_s << "\n"
351
- str_info << 'FREEMEMORY=' << free_mem.to_s << "\n"
352
- str_info << 'USEDMEMORY=' << (total_mem - free_mem).to_s << "\n"
353
-
354
- # DRS enabled
355
- str_info << 'VCENTER_DRS=' << drs_enabled.to_s << "\n"
356
-
357
- # HA enabled
358
- str_info << 'VCENTER_HA=' << ha_enabled.to_s << "\n"
359
-
360
- # NSX info
361
- str_info << nsx_get
362
- str_info << tz_get
363
-
364
- str_info << monitor_resource_pools(mhz_core)
365
- end
366
-
367
- def monitor_resource_pools(mhz_core)
368
- @rp_list = get_resource_pool_list
369
-
370
- view =
371
- @vi_client
372
- .vim
373
- .serviceContent
374
- .viewManager
375
- .CreateContainerView(
376
- {
377
- :container => @item, # View for RPs inside this cluster
378
- :type => ['ResourcePool'],
379
- :recursive => true
380
- }
381
- )
382
-
383
- pc = @vi_client.vim.serviceContent.propertyCollector
384
-
385
- monitored_properties = [
386
- 'config.cpuAllocation.expandableReservation',
387
- 'config.cpuAllocation.limit',
388
- 'config.cpuAllocation.reservation',
389
- 'config.cpuAllocation.shares.level',
390
- 'config.cpuAllocation.shares.shares',
391
- 'config.memoryAllocation.expandableReservation',
392
- 'config.memoryAllocation.limit',
393
- 'config.memoryAllocation.reservation',
394
- 'config.memoryAllocation.shares.level',
395
- 'config.memoryAllocation.shares.shares'
396
- ]
397
-
398
- filter_spec = RbVmomi::VIM.PropertyFilterSpec(
399
- :objectSet => [
400
- { :obj => view,
401
- :skip => true,
402
- :selectSet => [
403
- RbVmomi::VIM.TraversalSpec(
404
- :name => 'traverseEntities',
405
- :type => 'ContainerView',
406
- :path => 'view',
407
- :skip => false
408
- )
409
- ] }
410
- ],
411
- :propSet => [
412
- {
413
- :type => 'ResourcePool',
414
- :pathSet => monitored_properties
415
- }
416
- ]
417
- )
418
-
419
- result = pc.RetrieveProperties(:specSet => [filter_spec])
420
-
421
- rps = {}
422
- result.each do |r|
423
- hashed_properties = r.to_hash
424
- if r.obj.is_a?(RbVmomi::VIM::ResourcePool)
425
- rps[r.obj._ref] = hashed_properties
426
- end
427
- end
428
-
429
- return '' if rps.empty?
430
-
431
- rp_info = ''
432
-
433
- rps.each do |ref, info|
434
- # CPU
435
- if info['config.cpuAllocation.expandableReservation']
436
- cpu_expandable = 'YES'
437
- else
438
- cpu_expandable = 'NO'
439
- end
440
- if info['config.cpuAllocation.limit'] == '-1'
441
- cpu_limit = 'UNLIMITED'
442
- else
443
- cpu_limit = info['config.cpuAllocation.limit']
444
- end
445
- cpu_reservation = info['config.cpuAllocation.reservation']
446
- cpu_num = cpu_reservation.to_f / mhz_core
447
- cpu_shares_level = info['config.cpuAllocation.shares.level']
448
- cpu_shares = info['config.cpuAllocation.shares.shares']
449
-
450
- # MEMORY
451
- if info['config.memoryAllocation.expandableReservation']
452
- mem_expandable = 'YES'
453
- else
454
- mem_expandable = 'NO'
455
- end
456
- if info['config.memoryAllocation.limit'] == '-1'
457
- mem_limit = 'UNLIMITED'
458
- else
459
- mem_limit = info['config.memoryAllocation.limit']
460
- end
461
- mem_reservation =
462
- info['config.memoryAllocation.reservation'].to_f
463
- mem_shares_level =
464
- info['config.memoryAllocation.shares.level']
465
- mem_shares =
466
- info['config.memoryAllocation.shares.shares']
467
-
468
- rp_name =
469
- @rp_list
470
- .select do |item|
471
- item[:ref] == ref
472
- end.first[:name] rescue ''
473
-
474
- rp_name = 'Resources' if rp_name.empty?
475
-
476
- rp_info << "\nVCENTER_RESOURCE_POOL_INFO = ["
477
- rp_info << "NAME=\"#{rp_name}\","
478
- rp_info << "CPU_EXPANDABLE=#{cpu_expandable},"
479
- rp_info << "CPU_LIMIT=#{cpu_limit},"
480
- rp_info << "CPU_RESERVATION=#{cpu_reservation},"
481
- rp_info << "CPU_RESERVATION_NUM_CORES=#{cpu_num},"
482
- rp_info << "CPU_SHARES=#{cpu_shares},"
483
- rp_info << "CPU_SHARES_LEVEL=#{cpu_shares_level},"
484
- rp_info << "MEM_EXPANDABLE=#{mem_expandable},"
485
- rp_info << "MEM_LIMIT=#{mem_limit},"
486
- rp_info << "MEM_RESERVATION=#{mem_reservation},"
487
- rp_info << "MEM_SHARES=#{mem_shares},"
488
- rp_info << "MEM_SHARES_LEVEL=#{mem_shares_level}"
489
- rp_info << ']'
490
- end
491
-
492
- view.DestroyView
493
-
494
- rp_info
495
- end
496
-
497
- def hostname_to_moref(hostname)
498
- result = filter_hosts
499
-
500
- moref = ''
501
- result.each do |r|
502
- if r.obj.name == hostname
503
- moref = r.obj._ref
504
- break
505
- end
506
- end
507
- raise "Host #{hostname} was not found" if moref.empty?
508
-
509
- moref
510
- end
511
-
512
- def filter_hosts
513
- view =
514
- @vi_client
515
- .vim
516
- .serviceContent
517
- .viewManager
518
- .CreateContainerView(
519
- {
520
- # View for Hosts inside this cluster
521
- :container => @item,
522
- :type => ['HostSystem'],
523
- :recursive => true
524
- }
525
- )
526
-
527
- pc = @vi_client.vim.serviceContent.propertyCollector
528
-
529
- monitored_properties = [
530
- 'name',
531
- 'runtime.connectionState',
532
- 'summary.hardware.numCpuCores',
533
- 'summary.hardware.memorySize',
534
- 'summary.hardware.cpuModel',
535
- 'summary.hardware.cpuMhz',
536
- 'summary.quickStats.overallCpuUsage',
537
- 'summary.quickStats.overallMemoryUsage'
538
- ]
539
-
540
- filter_spec = RbVmomi::VIM.PropertyFilterSpec(
541
- :objectSet => [
542
- { :obj => view,
543
- :skip => true,
544
- :selectSet => [
545
- RbVmomi::VIM.TraversalSpec(
546
- :name => 'traverseEntities',
547
- :type => 'ContainerView',
548
- :path => 'view',
549
- :skip => false
550
- )
551
- ] }
552
- ],
553
- :propSet => [
554
- { :type => 'HostSystem', :pathSet => monitored_properties }
555
- ]
556
- )
557
-
558
- result = pc.RetrieveProperties(:specSet => [filter_spec])
559
- view.DestroyView # Destroy the view
560
- result
561
- end
562
-
563
- def monitor_host_systems
564
- host_info = ''
565
- result = filter_hosts
566
- hosts = {}
567
- result.each do |r|
568
- hashed_properties = r.to_hash
569
- if r.obj.is_a?(RbVmomi::VIM::HostSystem)
570
- hosts[r.obj._ref] = hashed_properties
571
- end
572
- end
573
-
574
- hosts.each do |_ref, info|
575
- next if info['runtime.connectionState'] != 'connected'
576
-
577
- total_cpu = info['summary.hardware.numCpuCores'] * 100
578
- used_cpu =
579
- (
580
- info['summary.quickStats.overallCpuUsage']
581
- .to_f / info['summary.hardware.cpuMhz']
582
- .to_f
583
- ) * 100
584
- # Trim precission
585
- used_cpu = format('%.2f', used_cpu).to_f # rubocop:disable Style/FormatStringToken
586
- free_cpu = total_cpu - used_cpu
587
-
588
- total_memory =
589
- info['summary.hardware.memorySize']/1024
590
- used_memory =
591
- info['summary.quickStats.overallMemoryUsage']*1024
592
- free_memory = total_memory - used_memory
593
-
594
- host_info << "\nHOST=["
595
- host_info << 'STATE=on,'
596
- host_info << 'HOSTNAME="' <<
597
- info['name'].to_s << '",'
598
- host_info <<
599
- 'MODELNAME="' <<
600
- info['summary.hardware.cpuModel'].to_s << '",'
601
- host_info << 'CPUSPEED=' <<
602
- info['summary.hardware.cpuMhz'].to_s << ','
603
- host_info << 'MAX_CPU=' << total_cpu.to_s << ','
604
- host_info << 'USED_CPU=' << used_cpu.to_s << ','
605
- host_info << 'FREE_CPU=' << free_cpu.to_s << ','
606
- host_info << 'MAX_MEM=' << total_memory.to_s << ','
607
- host_info << 'USED_MEM=' << used_memory.to_s << ','
608
- host_info << 'FREE_MEM=' << free_memory.to_s
609
- host_info << ']'
610
- end
611
-
612
- host_info
613
- end
614
-
615
- def monitor_vms(host_id, vm_type)
616
- vc_uuid = @vi_client.vim.serviceContent.about.instanceUuid
617
- cluster_name = self['name']
618
- cluster_ref = self['_ref']
619
-
620
- # Get info of the host where the VM/template is located
621
- one_host =
622
- VCenterDriver::VIHelper
623
- .one_item(
624
- OpenNebula::Host,
625
- host_id
626
- )
627
- if !one_host
628
- STDERR.puts "Failed to retieve host with id #{host.id}"
629
- if VCenterDriver::CONFIG[:debug_information]
630
- STDERR.puts "#{message} #{e.backtrace}"
631
- end
632
- end
633
-
634
- esx_hosts = {}
635
- @item.host.each do |esx_host|
636
- esx_hosts[esx_host._ref] = {
637
- :name => esx_host.name,
638
- :cpu => esx_host.summary.hardware.cpuMhz.to_f
639
- }
640
- end
641
-
642
- monitored_vms = Set.new
643
- str_info = ''
644
-
645
- view =
646
- @vi_client
647
- .vim
648
- .serviceContent
649
- .viewManager
650
- .CreateContainerView(
651
- {
652
- :container => @item, # View for VMs inside this cluster
653
- :type => ['VirtualMachine'],
654
- :recursive => true
655
- }
656
- )
657
-
658
- pc = @vi_client.vim.serviceContent.propertyCollector
659
-
660
- monitored_properties = [
661
- 'name', # VM name
662
- 'config.template', # To filter out templates
663
- 'summary.runtime.powerState', # VM power state
664
- 'summary.quickStats.hostMemoryUsage', # Memory usage
665
- 'summary.quickStats.overallCpuUsage', # CPU used by VM
666
- 'runtime.host', # ESX host
667
- 'resourcePool', # RP
668
- 'guest.guestFullName',
669
- # IP addresses as seen by guest tools,
670
- 'guest.net',
671
- 'guest.guestState',
672
- 'guest.toolsVersion',
673
- 'guest.toolsRunningStatus',
674
- # IP addresses as seen by guest tools,
675
- 'guest.toolsVersionStatus2',
676
- # VM extraconfig info e.g opennebula.vm.running
677
- 'config.extraConfig',
678
- 'config.hardware.numCPU',
679
- 'config.hardware.memoryMB',
680
- 'config.annotation',
681
- 'datastore'
682
- ]
683
-
684
- filter_spec = RbVmomi::VIM.PropertyFilterSpec(
685
- :objectSet => [
686
- { :obj => view,
687
- :skip => true,
688
- :selectSet => [
689
- RbVmomi::VIM.TraversalSpec(
690
- :name => 'traverseEntities',
691
- :type => 'ContainerView',
692
- :path => 'view',
693
- :skip => false
694
- )
695
- ] }
696
- ],
697
- :propSet => [
698
- {
699
- :type => 'VirtualMachine',
700
- :pathSet => monitored_properties
701
- }
702
- ]
703
- )
704
-
705
- result = pc.RetrieveProperties(:specSet => [filter_spec])
706
-
707
- vms = {}
708
- vm_objects = []
709
- result.each do |r|
710
- hashed_properties = r.to_hash
711
- next unless r.obj.is_a?(RbVmomi::VIM::VirtualMachine)
712
-
713
- # Only take care of VMs, not templates
714
- if !hashed_properties['config.template']
715
- vms[r.obj._ref + '_' + vc_uuid] = hashed_properties
716
- vm_objects << r.obj
717
- end
718
- end
719
-
720
- pm = @vi_client.vim.serviceContent.perfManager
721
-
722
- stats = {}
723
-
724
- max_samples = 9
725
- refresh_rate = 20 # Real time stats takes samples every 20 seconds
726
-
727
- last_mon_time = one_host['TEMPLATE/VCENTER_LAST_PERF_POLL']
728
-
729
- if last_mon_time
730
- interval = (Time.now.to_i - last_mon_time.to_i)
731
- interval = 3601 if interval < 0
732
- samples = (interval / refresh_rate)
733
- samples = 1 if samples == 0
734
- interval > 3600 ? max_samples = 9 : max_samples = samples
735
- end
736
-
737
- if !vm_objects.empty?
738
- stats = pm.retrieve_stats(
739
- vm_objects,
740
- [
741
- 'net.transmitted',
742
- 'net.bytesRx',
743
- 'net.bytesTx',
744
- 'net.received',
745
- 'virtualDisk.numberReadAveraged',
746
- 'virtualDisk.numberWriteAveraged',
747
- 'virtualDisk.read',
748
- 'virtualDisk.write'
749
- ],
750
- {
751
- :max_samples => max_samples
752
- }
753
- ) rescue {}
754
- end
755
-
756
- if !stats.empty?
757
- last_mon_time = Time.now.to_i.to_s
758
- end
759
-
760
- @rp_list ||= get_resource_pool_list
761
-
762
- vm_pool =
763
- VCenterDriver::VIHelper
764
- .one_pool(
765
- OpenNebula::VirtualMachinePool
766
- )
767
- # We filter to retrieve only those VMs
768
- # running in the host that we are monitoring
769
- host_vms =
770
- vm_pool
771
- .retrieve_xmlelements(
772
- "/VM_POOL/VM[HISTORY_RECORDS/HISTORY/HID='#{host_id}']"
773
- )
774
-
775
- vms.each do |vm_ref, info|
776
- vm_info = ''
777
- begin
778
- esx_host = esx_hosts[info['runtime.host']._ref]
779
- info[:esx_host_name] = esx_host[:name]
780
- info[:esx_host_cpu] = esx_host[:cpu]
781
- info[:cluster_name] = cluster_name
782
- info[:cluster_ref] = cluster_ref
783
- info[:vc_uuid] = vc_uuid
784
- info[:host_id] = host_id
785
- info[:rp_list] = @rp_list
786
-
787
- # Check the running flag
788
- running_flag = info['config.extraConfig'].select do |val|
789
- val[:key] == 'opennebula.vm.running'
790
- end
791
-
792
- if !running_flag.empty? && running_flag.first
793
- running_flag = running_flag[0][:value]
794
- end
795
-
796
- next if running_flag == 'no'
797
-
798
- id = -1
799
- # Find the VM by its deploy_id,
800
- # which in the vCenter driver is
801
- # the vCenter managed object reference
802
- found_vm =
803
- host_vms
804
- .select do |vm|
805
- vm['DEPLOY_ID'] == vm_ref ||
806
- vm['DEPLOY_ID'] == VIHelper.get_deploy_id(vm_ref)
807
- end.first
808
- id = found_vm['ID'] if found_vm
809
-
810
- # skip if it is a wild and
811
- # we are looking for OpenNebula VMs
812
- next if (vm_type == 'ones') && (id == -1)
813
- # skip if it is not a wild and we are looking for wilds
814
- next if (vm_type == 'wilds') && (id != -1)
815
- # skip if already monitored
816
- next if monitored_vms.include? vm_ref
817
-
818
- monitored_vms << vm_ref
819
-
820
- vm =
821
- VCenterDriver::VirtualMachine
822
- .new(
823
- @vi_client,
824
- vm_ref,
825
- id
826
- )
827
- vm.vm_info = info
828
- vm.monitor(stats)
829
-
830
- vm_name = "#{info['name']} - #{cluster_name}"
831
- vm_info << "VM = [ ID=\"#{id}\", "
832
- vm_info << "VM_NAME=\"#{vm_name}\", "
833
- vm_info << "DEPLOY_ID=\"#{vm_ref}\", "
834
-
835
- # if the machine does not exist in
836
- # opennebula it means that is a wild:
837
- if vm.one_exist?
838
- mon_s64 = Base64.strict_encode64(vm.info)
839
- vm_info << "MONITOR=\"#{mon_s64}\"]\n"
840
- else
841
- vm_template64 =
842
- Base64
843
- .encode64(
844
- vm.vm_to_one(vm_name)
845
- ).gsub("\n", '')
846
- vm_info << 'VCENTER_TEMPLATE="YES",'
847
- vm_info << "IMPORT_TEMPLATE=\"#{vm_template64}\"]\n"
848
- end
849
- rescue StandardError => e
850
- vm_info = error_monitoring(e, id, vm_ref, vc_uuid, info)
851
- end
852
-
853
- str_info << vm_info
854
- end
855
-
856
- view.DestroyView # Destroy the view
857
-
858
- [str_info, last_mon_time]
859
- end
860
-
861
- def error_monitoring(e, id, vm_ref, _vc_uuid, info = {})
862
- error_info = ''
863
- vm_name = info['name'] || nil
864
- tmp_str = e.inspect
865
- tmp_str << e.backtrace.join("\n")
866
-
867
- error_info << "VM = [ ID=\"#{id}\", "
868
- error_info << "VM_NAME=\"#{vm_name}\", "
869
- error_info << "DEPLOY_ID=\"#{vm_ref}\", "
870
- error_info <<
871
- "ERROR=\"#{Base64.encode64(tmp_str).gsub("\n", '')}\"]\n"
872
- end
873
-
874
- def monitor_customizations
875
- customizations =
876
- self['_connection']
877
- .serviceContent
878
- .customizationSpecManager
879
- .info
880
-
881
- text = ''
882
-
883
- customizations.each do |c|
884
- t = 'CUSTOMIZATION = [ '
885
- t << %(NAME = "#{c.name}", )
886
- t << %(TYPE = "#{c.type}" ]\n)
887
-
888
- text << t
889
- end
890
-
891
- text
892
- end
893
-
894
- def datacenter # rubocop:disable Naming/AccessorMethodName
895
- item = @item
896
-
897
- until item.instance_of? RbVmomi::VIM::Datacenter
898
- item = item.parent
899
- if item.nil?
900
- raise 'Could not find the parent Datacenter'
901
- end
902
- end
903
-
904
- Datacenter.new(item)
905
- end
906
-
907
- def self.to_one(cluster, con_ops, rp, one_cluster_id)
908
- one_host = VCenterDriver::VIHelper.new_one_item(OpenNebula::Host)
909
-
910
- if OpenNebula.is_error?(one_host)
911
- raise "Could not create host: #{one_host.message}"
912
- end
913
-
914
- one_cluster_id ||= -1
915
-
916
- rc = one_host
917
- .allocate(
918
- cluster[:cluster_name],
919
- 'vcenter',
920
- 'vcenter',
921
- one_cluster_id.to_i
922
- )
923
-
924
- if OpenNebula.is_error?(rc)
925
- raise "Could not allocate host: #{rc.message}"
926
- end
927
-
928
- template = "VCENTER_HOST=\"#{con_ops[:host]}\"\n"\
929
- "VCENTER_PASSWORD=\"#{con_ops[:password]}\"\n"\
930
- "VCENTER_USER=\"#{con_ops[:user]}\"\n"\
931
- "VCENTER_CCR_REF=\"#{cluster[:cluster_ref]}\"\n"\
932
- "VCENTER_INSTANCE_ID=\"#{cluster[:vcenter_uuid]}\"\n"\
933
- "VCENTER_VERSION=\"#{cluster[:vcenter_version]}\"\n"\
934
-
935
- template << "VCENTER_RESOURCE_POOL=\"#{rp}\"" if rp
936
-
937
- template << "VCENTER_PORT=\"#{con_ops[:port]}\"" if con_ops[:port]
938
-
939
- rc = one_host.update(template, false)
940
-
941
- if OpenNebula.is_error?(rc)
942
- update_error = rc.message
943
- rc = one_host.delete
944
-
945
- unless OpenNebula.is_error?(rc)
946
- raise "Could not update host: #{rc.message}"
947
- end
948
-
949
- raise "Could not update host: #{update_error} "\
950
- "and could not delete host: #{rc.message}"
951
- end
952
-
953
- rc = one_host.offline
954
-
955
- if OpenNebula.is_error?(rc)
956
- update_error = rc.message
957
- rc = one_host.delete
958
-
959
- unless OpenNebula.is_error?(rc)
960
- raise "Could not offline host: #{rc.message}"
961
- end
962
-
963
- raise "Could not offline host: #{update_error} "\
964
- "and could not delete host: #{rc.message}"
965
- end
966
-
967
- rc = one_host.enable
968
-
969
- if OpenNebula.is_error?(rc)
970
- update_error = rc.message
971
- rc = one_host.delete
972
-
973
- unless OpenNebula.is_error?(rc)
974
- raise "Could not enable host: #{rc.message}"
975
- end
976
-
977
- raise "Could not enable host: #{update_error} "\
978
- "and could not delete host: #{rc.message}"
979
- end
980
-
981
- one_host
982
- end
983
-
984
- def self.new_from_ref(ref, vi_client)
985
- new(
986
- RbVmomi::VIM::ClusterComputeResource
987
- .new(
988
- vi_client.vim,
989
- ref
990
- ),
991
- vi_client
992
- )
993
- end
994
-
995
- end
996
- # class ClusterComputeResource
997
-
998
- ##########################################################################
999
- # Class ESXHost
1000
- ##########################################################################
1001
- class ESXHost
1002
-
1003
- attr_accessor :item
1004
-
1005
- include Memoize
1006
-
1007
- PG_CREATE_TIMEOUT = 240 # We will wait for 4 minutes for the pg creation
1008
-
1009
- def initialize(item, vi_client = nil)
1010
- @net_rollback = []
1011
- @locking = true
1012
- @item = item
1013
- @vi_client = vi_client
1014
- end
1015
-
1016
- def self.new_from_ref(ref, vi_client)
1017
- new(RbVmomi::VIM::HostSystem.new(vi_client.vim, ref), vi_client)
1018
- end
1019
-
1020
- # Locking function. Similar to flock
1021
- def lock
1022
- hostlockname = @item['name'].downcase.tr(' ', '_')
1023
-
1024
- return unless @locking
1025
-
1026
- @locking_file =
1027
- File
1028
- .open("/tmp/vcenter-#{hostlockname}-lock", 'w')
1029
- @locking_file.flock(File::LOCK_EX)
1030
- end
1031
-
1032
- # Unlock driver execution mutex
1033
- def unlock
1034
- return unless @locking
1035
-
1036
- @locking_file.close
1037
- end
1038
-
1039
- ########################################################################
1040
- # Check if standard switch exists in host
1041
- ########################################################################
1042
-
1043
- def vss_exists(vswitch_name)
1044
- vswitches = @item.configManager.networkSystem.networkInfo.vswitch
1045
- vswitches.select {|vs| vs.name == vswitch_name }.first rescue nil
1046
- end
1047
-
1048
- ########################################################################
1049
- # Create a standard vcenter switch in an ESX host
1050
- ########################################################################
1051
-
1052
- def create_vss(
1053
- name,
1054
- num_ports,
1055
- pnics = nil,
1056
- mtu = 1500,
1057
- pnics_available = nil
1058
- )
1059
- # Get NetworkSystem
1060
- nws = self['configManager.networkSystem']
1061
- hostbridge = nil
1062
- nics = []
1063
-
1064
- num_ports = 128 if num_ports.nil?
1065
-
1066
- if pnics
1067
- pnics = pnics.split(',')
1068
- pnics.each do |pnic|
1069
- # Add nics if not in use
1070
- nics << pnic if pnics_available.include?(pnic)
1071
- end
1072
-
1073
- if !nics.empty?
1074
- hostbridge =
1075
- RbVmomi::VIM::HostVirtualSwitchBondBridge(
1076
- :nicDevice => nics
1077
- )
1078
- end
1079
- end
1080
-
1081
- # Create spec
1082
- vswitchspec =
1083
- RbVmomi::VIM::HostVirtualSwitchSpec(
1084
- :bridge => hostbridge,
1085
- :mtu => mtu,
1086
- :numPorts => num_ports
1087
- )
1088
-
1089
- # add vSwitch to the host
1090
- begin
1091
- nws.AddVirtualSwitch(:vswitchName => name, :spec => vswitchspec)
1092
- rescue StandardError => e
1093
- raise "The standard vSwitch #{name} could not be \
1094
- created. AddVirtualSwitch failed Reason: #{e.message}."
1095
- end
1096
-
1097
- @net_rollback << { :action => :delete_sw, :name => name }
1098
-
1099
- name
1100
- end
1101
-
1102
- ########################################################################
1103
- # Update a standard vcenter switch in an ESX host
1104
- ########################################################################
1105
- def update_vss(switch, name, pnics, num_ports, mtu)
1106
- pnics = pnics.split(',') rescue []
1107
-
1108
- # Backup switch spec for rollback
1109
- orig_spec = switch.spec
1110
-
1111
- # Compare current configuration and return if switch hasn't changed
1112
- switch_has_pnics = switch
1113
- .spec
1114
- .respond_to?(
1115
- :bridge
1116
- ) && switch
1117
- .spec
1118
- .bridge
1119
- .respond_to?(
1120
- :nicDevice
1121
- )
1122
-
1123
- same_switch = switch.spec.respond_to?(:mtu) && switch
1124
- .spec
1125
- .mtu == mtu &&
1126
- switch
1127
- .spec
1128
- .respond_to?(
1129
- :numPorts
1130
- ) && switch.spec.numPorts == num_ports &&
1131
- (!switch_has_pnics && pnics.empty? ||
1132
- switch_has_pnics && switch
1133
- .spec
1134
- .bridge
1135
- .nicDevice
1136
- .uniq
1137
- .sort == pnics.uniq.sort)
1138
- return if same_switch
1139
-
1140
- # Let's create a new spec and update the switch
1141
- hostbridge = nil
1142
- nws = self['configManager.networkSystem']
1143
- unless pnics.empty?
1144
- hostbridge =
1145
- RbVmomi::VIM::HostVirtualSwitchBondBridge(
1146
- :nicDevice => pnics
1147
- )
1148
- end
1149
- vswitchspec =
1150
- RbVmomi::VIM::HostVirtualSwitchSpec(
1151
- :bridge => hostbridge,
1152
- :mtu => mtu,
1153
- :numPorts => num_ports
1154
- )
1155
- begin
1156
- nws
1157
- .UpdateVirtualSwitch(
1158
- :vswitchName => name,
1159
- :spec => vswitchspec
1160
- )
1161
- rescue StandardError => e
1162
- raise "The standard switch with name #{name} \
1163
- could not be updated. Reason: #{e.message}"
1164
- end
1165
-
1166
- @net_rollback << {
1167
- :action => :update_sw,
1168
- :name => name,
1169
- :spec => orig_spec
1170
- }
1171
- end
1172
-
1173
- ########################################################################
1174
- # Remove a standard vswitch from the host
1175
- ########################################################################
1176
- def remove_vss(vswitch_name)
1177
- nws = self['configManager.networkSystem']
1178
-
1179
- begin
1180
- nws.RemoveVirtualSwitch(:vswitchName => vswitch_name)
1181
- rescue RbVmomi::VIM::ResourceInUse
1182
- STDERR.puts "The standard switch #{vswitch_name} \
1183
- is in use so it cannot be deleted"
1184
- return
1185
- rescue RbVmomi::VIM::NotFound
1186
- STDERR.puts "The standard switch #{vswitch_name} \
1187
- was not found in vCenter"
1188
- return
1189
- rescue StandardError => e
1190
- raise "There was a failure while deleting a vcenter \
1191
- standard switch #{vswitch_name}. Reason: #{e.message}"
1192
- end
1193
-
1194
- vswitch_name
1195
- end
1196
-
1197
- ########################################################################
1198
- # Get physical nics that are available in a host
1199
- ########################################################################
1200
- def available_pnics
1201
- pnics_in_use = []
1202
- pnics_available = []
1203
-
1204
- # Get pnics in use in standard switches
1205
- @item.config.network.vswitch.each do |vs|
1206
- vs.pnic.each do |pnic|
1207
- next unless pnic.instance_of?(String)
1208
-
1209
- pnic.slice!('key-vim.host.PhysicalNic-')
1210
- pnics_in_use << pnic
1211
- end
1212
- end
1213
-
1214
- # Get pnics in host
1215
- self['config.network'].pnic.each do |pnic|
1216
- next if pnics_in_use
1217
- .include?(pnic.device)
1218
-
1219
- pnics_available << pnic
1220
- .device
1221
- end
1222
-
1223
- pnics_available
1224
- end
1225
-
1226
- ########################################################################
1227
- # Get networks inside a host
1228
- ########################################################################
1229
- def pg_inside_host
1230
- pg_inside = {}
1231
-
1232
- # Get pnics in use in standard switches
1233
- @item.config.network.vswitch.each do |vs|
1234
- pg_inside[vs.name] = []
1235
- vs.portgroup.each do |pg|
1236
- pg.slice!('key-vim.host.PortGroup-')
1237
- pg_inside[vs.name] << pg
1238
- end
1239
- end
1240
-
1241
- pg_inside
1242
- end
1243
-
1244
- ########################################################################
1245
- # Check if proxy switch exists in host for distributed virtual switch
1246
- ########################################################################
1247
-
1248
- def proxy_switch_exists(switch_name)
1249
- nws = self['configManager.networkSystem']
1250
- proxy_switches = nws.networkInfo.proxySwitch
1251
- proxy_switches
1252
- .select {|ps| ps.dvsName == switch_name }
1253
- .first rescue nil
1254
- end
1255
-
1256
- ########################################################################
1257
- # Assign a host to a a distributed vcenter switch (proxy switch)
1258
- ########################################################################
1259
-
1260
- def assign_proxy_switch(dvs, switch_name, pnics, _pnics_available)
1261
- dvs = dvs.item
1262
-
1263
- # Return if host is already assigned
1264
- return dvs unless dvs['config.host']
1265
- .select do |host|
1266
- host.config.host._ref == self['_ref']
1267
- end.empty?
1268
-
1269
- # Prepare spec for DVS reconfiguration
1270
- config_spec = RbVmomi::VIM::VMwareDVSConfigSpec.new
1271
- config_spec.name = switch_name
1272
- config_spec.configVersion = dvs['config.configVersion']
1273
-
1274
- # Check if host is already assigned to distributed switch
1275
- operation = 'add'
1276
- # #operation = "edit" if !dvs['config.host'].select
1277
- # { |host| host.config.host._ref == self['_ref'] }.empty?
1278
-
1279
- # Add host members to the distributed virtual switch
1280
- host_member_spec =
1281
- RbVmomi::VIM::DistributedVirtualSwitchHostMemberConfigSpec
1282
- .new
1283
- host_member_spec.host = @item
1284
- host_member_spec.operation = operation
1285
- host_member_spec.backing =
1286
- RbVmomi::VIM::DistributedVirtualSwitchHostMemberPnicBacking
1287
- .new
1288
- host_member_spec.backing.pnicSpec = []
1289
-
1290
- # If pnics are needed assign pnics for uplinks
1291
- if pnics
1292
- pnics = pnics.split(',')
1293
- # Get uplink portgroup from dvswitch
1294
- uplink_key = dvs['config.uplinkPortgroup'].select do |ul|
1295
- ul.name == "#{switch_name}-uplink-pg"
1296
- end.first.key rescue nil
1297
-
1298
- unless uplink_key
1299
- raise "Cannot find the uplink portgroup for #{switch_name}"
1300
- end
1301
-
1302
- pnics.each do |pnic|
1303
- pnic_spec =
1304
- RbVmomi::VIM::DistributedVirtualSwitchHostMemberPnicSpec
1305
- .new
1306
- pnic_spec.pnicDevice = pnic
1307
- pnic_spec.uplinkPortgroupKey = uplink_key
1308
- host_member_spec.backing.pnicSpec << pnic_spec
1309
- end
1310
- end
1311
-
1312
- config_spec.host = [host_member_spec]
1313
-
1314
- # The DVS must be reconfigured
1315
- dvs_reconfigure_task = dvs.ReconfigureDvs_Task(:spec => config_spec)
1316
- dvs_reconfigure_task.wait_for_completion
1317
- if dvs_reconfigure_task.info.state != 'success'
1318
- raise "It wasn't possible to assign host \
1319
- #{self['name']} as a member of #{switch_name}'"
1320
- end
1321
-
1322
- dvs
1323
- end
1324
-
1325
- ########################################################################
1326
- # Create a standard port group
1327
- ########################################################################
1328
-
1329
- def create_pg(pgname, vswitch, vlan = 0)
1330
- spec = RbVmomi::VIM.HostPortGroupSpec(
1331
- :name => pgname,
1332
- :vlanId => vlan,
1333
- :vswitchName => vswitch,
1334
- :policy => RbVmomi::VIM.HostNetworkPolicy
1335
- )
1336
-
1337
- nws = self['configManager.networkSystem']
1338
-
1339
- begin
1340
- nws.AddPortGroup(:portgrp => spec)
1341
- rescue StandardError => e
1342
- raise "A port group with name #{pgname} \
1343
- could not be created. Reason: #{e.message}"
1344
- end
1345
-
1346
- @net_rollback << { :action => :delete_pg, :name => pgname }
1347
-
1348
- # wait until the network is ready and we have a reference
1349
- networks = @item['network'].select {|net| net.name == pgname }
1350
- (0..PG_CREATE_TIMEOUT).each do
1351
- break unless networks.empty?
1352
-
1353
- networks = @item['network'].select {|net| net.name == pgname }
1354
- sleep 1
1355
- end
1356
-
1357
- if networks.empty?
1358
- raise 'Cannot get VCENTER_NET_REF for new port group'
1359
- end
1360
-
1361
- networks.first._ref
1362
- end
1363
-
1364
- ########################################################################
1365
- # Check if standard port group exists in host
1366
- ########################################################################
1367
-
1368
- def pg_exists(pg_name)
1369
- nws = self['configManager.networkSystem']
1370
- portgroups = nws.networkInfo.portgroup
1371
- portgroups.select {|pg| pg.spec.name == pg_name }.first rescue nil
1372
- end
1373
-
1374
- ########################################################################
1375
- # Is the switch for the pg different?
1376
- ########################################################################
1377
-
1378
- def pg_changes_sw?(pg, switch_name)
1379
- pg
1380
- .spec
1381
- .respond_to?(
1382
- :vswitchName
1383
- ) && pg
1384
- .spec
1385
- .vswitchName != switch_name
1386
- end
1387
-
1388
- ########################################################################
1389
- # Update a standard port group
1390
- ########################################################################
1391
-
1392
- def update_pg(pg, switch_name, vlan_id)
1393
- unless pg.spec.respond_to?(:vlanId) && pg.spec.vlanId != vlan_id
1394
- return
1395
- end
1396
-
1397
- # Backup original spec
1398
- orig_spec = pg.spec
1399
-
1400
- # Create new spec
1401
- pg_name = pg.spec.name
1402
-
1403
- spec = RbVmomi::VIM.HostPortGroupSpec(
1404
- :name => pg_name,
1405
- :vlanId => vlan_id,
1406
- :vswitchName => switch_name,
1407
- :policy => RbVmomi::VIM.HostNetworkPolicy
1408
- )
1409
-
1410
- nws = self['configManager.networkSystem']
1411
-
1412
- begin
1413
- nws.UpdatePortGroup(:pgName => pg_name, :portgrp => spec)
1414
- rescue StandardError => e
1415
- raise "A port group with name #{pg_name} \
1416
- could not be updated. Reason: #{e.message}"
1417
- end
1418
-
1419
- # Set rollback operation
1420
- @net_rollback << {
1421
- :action => :update_pg,
1422
- :name => pg_name,
1423
- :spec => orig_spec
1424
- }
1425
- end
1426
-
1427
- ########################################################################
1428
- # Remove a standard port group from the host
1429
- ########################################################################
1430
-
1431
- def remove_pg(pgname)
1432
- nws = self['configManager.networkSystem']
1433
-
1434
- swname = nil
1435
- begin
1436
- portgroups = nws.networkConfig.portgroup
1437
- portgroups.each do |pg|
1438
- if pg.spec.name == pgname
1439
- swname = pg.spec.vswitchName
1440
- break
1441
- end
1442
- end
1443
- nws.RemovePortGroup(:pgName => pgname)
1444
- rescue RbVmomi::VIM::ResourceInUse
1445
- STDERR.puts "The standard portgroup \
1446
- #{pgname} is in use so it cannot be deleted"
1447
- return
1448
- rescue RbVmomi::VIM::NotFound
1449
- STDERR.puts "The standard portgroup \
1450
- #{pgname} was not found in vCenter"
1451
- return
1452
- rescue StandardError => e
1453
- raise "There was a failure while \
1454
- deleting a standard portgroup #{pgname} \
1455
- in vCenter. Reason: #{e.message}"
1456
- end
1457
-
1458
- swname
1459
- end
1460
-
1461
- def network_rollback
1462
- nws = self['configManager.networkSystem']
1463
-
1464
- @net_rollback.reverse_each do |nr|
1465
- case nr[:action]
1466
- when :update_pg
1467
- begin
1468
- nws
1469
- .UpdatePortGroup(
1470
- :pgName => nr[:name],
1471
- :portgrp => nr[:spec]
1472
- )
1473
- rescue StandardError => e
1474
- raise "A rollback operation for standard \
1475
- port group #{nr[:name]} could not \
1476
- be performed. Reason: #{e.message}"
1477
- end
1478
- when :update_sw
1479
- begin
1480
- nws
1481
- .UpdateVirtualSwitch(
1482
- :vswitchName => nr[:name],
1483
- :spec => nr[:spec]
1484
- )
1485
- rescue StandardError => e
1486
- raise "A rollback operation for standard \
1487
- switch #{nr[:name]} could not \
1488
- be performed. Reason: #{e.message}"
1489
- end
1490
- when :delete_sw
1491
- begin
1492
- nws.RemoveVirtualSwitch(:vswitchName=> nr[:name])
1493
- rescue RbVmomi::VIM::ResourceInUse
1494
- next # Ignore if switch in use
1495
- rescue RbVmomi::VIM::NotFound
1496
- next # Ignore if switch not found
1497
- rescue StandardError => e
1498
- raise "A rollback operation for standard \
1499
- switch #{nr[:name]} could not \
1500
- be performed. Reason: #{e.message}"
1501
- end
1502
- when :delete_pg
1503
- begin
1504
- nws.RemovePortGroup(:pgName => nr[:name])
1505
- rescue RbVmomi::VIM::ResourceInUse
1506
- next # Ignore if pg in use
1507
- rescue RbVmomi::VIM::NotFound
1508
- next # Ignore if pg not found
1509
- rescue StandardError => e
1510
- raise "A rollback operation for \
1511
- standard port group #{nr[:name]} could \
1512
- not be performed. Reason: #{e.message}"
1513
- end
1514
- end
1515
- end
1516
- end
1517
-
1518
- end
1519
- # class ESXHost
1520
-
1521
- end
1522
- # module VCenterDriver