rbvmomi2 3.0.0 → 3.0.1
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.
- checksums.yaml +4 -4
- data/README.md +11 -25
- data/exe/rbvmomish +50 -48
- data/lib/rbvmomi/basic_types.rb +318 -294
- data/lib/rbvmomi/connection.rb +221 -216
- data/lib/rbvmomi/deserialization.rb +201 -205
- data/lib/rbvmomi/fault.rb +10 -9
- data/lib/rbvmomi/optimist.rb +51 -50
- data/lib/rbvmomi/pbm.rb +52 -50
- data/lib/rbvmomi/sms/SmsStorageManager.rb +2 -1
- data/lib/rbvmomi/sms.rb +48 -46
- data/lib/rbvmomi/sso.rb +13 -18
- data/lib/rbvmomi/trivial_soap.rb +9 -8
- data/lib/rbvmomi/type_loader.rb +100 -101
- data/lib/rbvmomi/utils/admission_control.rb +90 -106
- data/lib/rbvmomi/utils/deploy.rb +77 -85
- data/lib/rbvmomi/utils/leases.rb +31 -33
- data/lib/rbvmomi/utils/perfdump.rb +177 -207
- data/lib/rbvmomi/version.rb +2 -1
- data/lib/rbvmomi/vim/ComputeResource.rb +17 -15
- data/lib/rbvmomi/vim/Datacenter.rb +1 -0
- data/lib/rbvmomi/vim/Datastore.rb +18 -15
- data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +7 -6
- data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +3 -2
- data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +7 -6
- data/lib/rbvmomi/vim/Folder.rb +37 -33
- data/lib/rbvmomi/vim/HostSystem.rb +139 -136
- data/lib/rbvmomi/vim/ManagedEntity.rb +15 -14
- data/lib/rbvmomi/vim/ManagedObject.rb +11 -10
- data/lib/rbvmomi/vim/ObjectContent.rb +3 -1
- data/lib/rbvmomi/vim/ObjectUpdate.rb +3 -1
- data/lib/rbvmomi/vim/OvfManager.rb +50 -57
- data/lib/rbvmomi/vim/PerfCounterInfo.rb +4 -3
- data/lib/rbvmomi/vim/PerformanceManager.rb +28 -31
- data/lib/rbvmomi/vim/PropertyCollector.rb +8 -7
- data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +22 -21
- data/lib/rbvmomi/vim/ResourcePool.rb +19 -18
- data/lib/rbvmomi/vim/ServiceInstance.rb +8 -7
- data/lib/rbvmomi/vim/Task.rb +6 -5
- data/lib/rbvmomi/vim/VirtualMachine.rb +8 -7
- data/lib/rbvmomi/vim.rb +112 -129
- data/lib/rbvmomi.rb +1 -0
- metadata +54 -10
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2012-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
@@ -7,28 +8,28 @@ require 'yaml'
|
|
7
8
|
# PerfAggregator is a class that, given connections to a list of vCenter
|
8
9
|
# Servers, will fetch the entire VM folder and ResourcePool hierarchies,
|
9
10
|
# including all VIM::VirtualMachine objects and aggregate VM stats along
|
10
|
-
# the tree hierarchies. The PerfAggregator class allows for users to
|
11
|
+
# the tree hierarchies. The PerfAggregator class allows for users to
|
11
12
|
# perform post processing on the data returned by vCenter, e.g. to augment
|
12
|
-
# it with addtional data that was obtained using a combination of
|
13
|
+
# it with addtional data that was obtained using a combination of
|
13
14
|
# VM annotations (or custom values) and an external DB. Post processing
|
14
|
-
# can also define additional tree structures that may be completely
|
15
|
+
# can also define additional tree structures that may be completely
|
15
16
|
# independent of the VM folder and ResourcePool hirarchies provided by
|
16
17
|
# vCenter, e.g. one based on VMs used for testing of a set of source code
|
17
|
-
# branches.
|
18
|
+
# branches.
|
18
19
|
class PerfAggregator
|
19
20
|
attr_accessor :path_types
|
20
|
-
|
21
|
+
|
21
22
|
def initialize logger = nil
|
22
23
|
@logger = logger
|
23
|
-
@path_types = Set.new
|
24
|
+
@path_types = Set.new
|
24
25
|
@path_types << 'rp'
|
25
26
|
@path_types << 'vmfolder'
|
26
|
-
|
27
|
+
|
27
28
|
# XXX: Rename this variable
|
28
29
|
@perf_metrics = {
|
29
|
-
'virtualDisk.read' => :sum,
|
30
|
+
'virtualDisk.read' => :sum,
|
30
31
|
'virtualDisk.write' => :sum,
|
31
|
-
'virtualDisk.numberReadAveraged' => :sum,
|
32
|
+
'virtualDisk.numberReadAveraged' => :sum,
|
32
33
|
'virtualDisk.numberWriteAveraged' => :sum,
|
33
34
|
'virtualDisk.totalReadLatency.avg' => :avg_ignore_zero,
|
34
35
|
'virtualDisk.totalWriteLatency.avg' => :avg_ignore_zero,
|
@@ -46,28 +47,26 @@ class PerfAggregator
|
|
46
47
|
'storage.space.unshared' => :sum,
|
47
48
|
}
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
def log text
|
51
52
|
if @logger
|
52
|
-
@logger.info text
|
53
|
+
@logger.info text
|
53
54
|
else
|
54
55
|
puts "#{Time.now}: #{text}"
|
55
56
|
end
|
56
57
|
end
|
57
|
-
|
58
|
+
|
58
59
|
def set_vm_processing_callback &block
|
59
60
|
@vm_processing_callback = block
|
60
61
|
end
|
61
|
-
|
62
|
+
|
62
63
|
def add_node_unless_exists inventory, id, props
|
63
|
-
if !inventory[id]
|
64
|
-
inventory[id] = props.merge({'children' => []})
|
65
|
-
end
|
64
|
+
inventory[id] = props.merge({'children' => []}) if !inventory[id]
|
66
65
|
end
|
67
|
-
|
66
|
+
|
68
67
|
# Method that extracts the entire VM folder and ResourcePool hierarchy
|
69
|
-
# from vCenter with a single API call. It generates a flat list of
|
70
|
-
# VIM objects which will include VIM::Folder, VIM::Datacenter,
|
68
|
+
# from vCenter with a single API call. It generates a flat list of
|
69
|
+
# VIM objects which will include VIM::Folder, VIM::Datacenter,
|
71
70
|
# VIM::ClusterComputeResource, VIM::ResourcePool and VIM::VirtualMachine.
|
72
71
|
#
|
73
72
|
# Post processing is done (using helper methods) to populate full paths,
|
@@ -82,87 +81,87 @@ class PerfAggregator
|
|
82
81
|
def all_inventory_flat rootFolder, vm_prop_names = ['name']
|
83
82
|
conn = rootFolder._connection
|
84
83
|
pc = conn.propertyCollector
|
85
|
-
|
84
|
+
|
86
85
|
filterSpec = RbVmomi::VIM.PropertyFilterSpec(
|
87
|
-
:
|
88
|
-
:
|
89
|
-
:
|
86
|
+
objectSet: [
|
87
|
+
obj: rootFolder,
|
88
|
+
selectSet: [
|
90
89
|
RbVmomi::VIM.TraversalSpec(
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
94
|
-
:
|
95
|
-
:
|
96
|
-
RbVmomi::VIM.SelectionSpec(:
|
97
|
-
RbVmomi::VIM.SelectionSpec(:
|
98
|
-
RbVmomi::VIM.SelectionSpec(:
|
99
|
-
RbVmomi::VIM.SelectionSpec(:
|
100
|
-
RbVmomi::VIM.SelectionSpec(:
|
90
|
+
name: 'tsFolder',
|
91
|
+
type: 'Folder',
|
92
|
+
path: 'childEntity',
|
93
|
+
skip: false,
|
94
|
+
selectSet: [
|
95
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsFolder'),
|
96
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsDatacenterVmFolder'),
|
97
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsDatacenterHostFolder'),
|
98
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsClusterRP'),
|
99
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsClusterHost'),
|
101
100
|
]
|
102
101
|
),
|
103
102
|
RbVmomi::VIM.TraversalSpec(
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
109
|
-
RbVmomi::VIM.SelectionSpec(:
|
103
|
+
name: 'tsDatacenterVmFolder',
|
104
|
+
type: 'Datacenter',
|
105
|
+
path: 'vmFolder',
|
106
|
+
skip: false,
|
107
|
+
selectSet: [
|
108
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsFolder')
|
110
109
|
]
|
111
110
|
),
|
112
111
|
RbVmomi::VIM.TraversalSpec(
|
113
|
-
:
|
114
|
-
:
|
115
|
-
:
|
116
|
-
:
|
117
|
-
:
|
118
|
-
RbVmomi::VIM.SelectionSpec(:
|
112
|
+
name: 'tsDatacenterHostFolder',
|
113
|
+
type: 'Datacenter',
|
114
|
+
path: 'hostFolder',
|
115
|
+
skip: false,
|
116
|
+
selectSet: [
|
117
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsFolder')
|
119
118
|
]
|
120
119
|
),
|
121
120
|
RbVmomi::VIM.TraversalSpec(
|
122
|
-
:
|
123
|
-
:
|
124
|
-
:
|
125
|
-
:
|
126
|
-
:
|
127
|
-
RbVmomi::VIM.SelectionSpec(:
|
121
|
+
name: 'tsClusterRP',
|
122
|
+
type: 'ClusterComputeResource',
|
123
|
+
path: 'resourcePool',
|
124
|
+
skip: false,
|
125
|
+
selectSet: [
|
126
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsRP'),
|
128
127
|
]
|
129
128
|
),
|
130
129
|
RbVmomi::VIM.TraversalSpec(
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
130
|
+
name: 'tsClusterHost',
|
131
|
+
type: 'ClusterComputeResource',
|
132
|
+
path: 'host',
|
133
|
+
skip: false,
|
134
|
+
selectSet: []
|
136
135
|
),
|
137
136
|
RbVmomi::VIM.TraversalSpec(
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
RbVmomi::VIM.SelectionSpec(:
|
137
|
+
name: 'tsRP',
|
138
|
+
type: 'ResourcePool',
|
139
|
+
path: 'resourcePool',
|
140
|
+
skip: false,
|
141
|
+
selectSet: [
|
142
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsRP'),
|
144
143
|
]
|
145
144
|
),
|
146
145
|
]
|
147
146
|
],
|
148
|
-
:
|
149
|
-
{ :
|
150
|
-
{ :
|
151
|
-
{ :
|
152
|
-
:
|
147
|
+
propSet: [
|
148
|
+
{ type: 'Folder', pathSet: ['name', 'parent'] },
|
149
|
+
{ type: 'Datacenter', pathSet: ['name', 'parent'] },
|
150
|
+
{ type: 'ClusterComputeResource',
|
151
|
+
pathSet: ['name', 'parent', 'summary.effectiveCpu', 'summary.effectiveMemory']
|
153
152
|
},
|
154
|
-
{ :
|
155
|
-
{ :
|
156
|
-
{ :
|
153
|
+
{ type: 'ResourcePool', pathSet: ['name', 'parent'] },
|
154
|
+
{ type: 'HostSystem', pathSet: ['name', 'parent', 'runtime.connectionState'] },
|
155
|
+
{ type: 'VirtualMachine', pathSet: vm_prop_names },
|
157
156
|
]
|
158
157
|
)
|
159
|
-
|
160
|
-
result = pc.RetrieveProperties(:
|
158
|
+
|
159
|
+
result = pc.RetrieveProperties(specSet: [filterSpec])
|
161
160
|
inventory = {}
|
162
161
|
vms = {}
|
163
|
-
result.each do |r|
|
162
|
+
result.each do |r|
|
164
163
|
if r.obj.is_a?(RbVmomi::VIM::VirtualMachine)
|
165
|
-
vms[r.obj] = r.to_hash
|
164
|
+
vms[r.obj] = r.to_hash
|
166
165
|
else
|
167
166
|
inventory[r.obj] = r.to_hash
|
168
167
|
end
|
@@ -179,20 +178,19 @@ class PerfAggregator
|
|
179
178
|
'parent' => 'root',
|
180
179
|
'parents' => ['root'],
|
181
180
|
}
|
182
|
-
_compute_vmfolders_and_rp_paths conn.host, inventory
|
181
|
+
_compute_vmfolders_and_rp_paths conn.host, inventory
|
183
182
|
_compute_parents_and_children inventory
|
184
183
|
[vms, inventory]
|
185
184
|
end
|
186
|
-
|
187
|
-
# Helper method that computes full paths and parent lists out of a
|
185
|
+
|
186
|
+
# Helper method that computes full paths and parent lists out of a
|
188
187
|
# flat list of objects. Operates recursively and doesn't yet split
|
189
188
|
# the paths into different tree types.
|
190
189
|
# @param obj [Hash] Property hash of current element
|
191
190
|
# @param objs [Array] Flat list of tree elements
|
192
191
|
def _compute_vmfolder_and_rp_path_and_parents vc, obj, objs
|
193
|
-
if obj['path']
|
194
|
-
|
195
|
-
end
|
192
|
+
return if obj['path']
|
193
|
+
|
196
194
|
if !obj['parent']
|
197
195
|
obj['parent'] = vc
|
198
196
|
obj['path'] = "root/#{vc}/#{obj['name']}"
|
@@ -201,23 +199,23 @@ class PerfAggregator
|
|
201
199
|
end
|
202
200
|
parent = objs[obj['parent']]
|
203
201
|
_compute_vmfolder_and_rp_path_and_parents(vc, parent, objs)
|
204
|
-
obj['path'] =
|
202
|
+
obj['path'] = '%s/%s' % [parent['path'], obj['name']]
|
205
203
|
obj['parents'] = [obj['parent']] + parent['parents']
|
206
204
|
nil
|
207
205
|
end
|
208
|
-
|
209
|
-
# Helper method that computes full paths and parent lists out of a
|
206
|
+
|
207
|
+
# Helper method that computes full paths and parent lists out of a
|
210
208
|
# flat list of objects. Full paths are tracked seperately per type
|
211
209
|
# of tree, i.e. seperately for the ResourcePool tree and the VM folder
|
212
|
-
# tree.
|
210
|
+
# tree.
|
213
211
|
# @param objs [Array] Flat list of tree elements
|
214
212
|
def _compute_vmfolders_and_rp_paths vc, objs
|
215
|
-
objs.each do |obj, props|
|
213
|
+
objs.each do |obj, props|
|
216
214
|
_compute_vmfolder_and_rp_path_and_parents(vc, props, objs)
|
217
|
-
|
215
|
+
|
218
216
|
props['paths'] = {}
|
219
217
|
obj_with_parents = [obj] + props['parents']
|
220
|
-
dc = obj_with_parents.find{|x| x.is_a?(RbVmomi::VIM::Datacenter)}
|
218
|
+
dc = obj_with_parents.find{ |x| x.is_a?(RbVmomi::VIM::Datacenter) }
|
221
219
|
# Everything above and including a VIM::Datacenter is part of
|
222
220
|
# both the rp and vmfolder tree. Anything below depends on the
|
223
221
|
# folder of the datacenter it is under: The hostFolder is called
|
@@ -234,24 +232,22 @@ class PerfAggregator
|
|
234
232
|
props['paths']['vmfolder'] = props['path']
|
235
233
|
end
|
236
234
|
end
|
237
|
-
|
235
|
+
|
238
236
|
props['children'] = []
|
239
237
|
end
|
240
238
|
end
|
241
|
-
|
239
|
+
|
242
240
|
# Helper method that computes children references and parent paths on
|
243
241
|
# all objects, if not computed yet. Assumes that full paths of each
|
244
242
|
# object have been calculated already.
|
245
243
|
# @param objs [Array] Flat list of tree elements
|
246
244
|
def _compute_parents_and_children objs
|
247
245
|
objs.each do |obj, props|
|
248
|
-
if props['parent_paths']
|
249
|
-
|
250
|
-
end
|
246
|
+
next if props['parent_paths']
|
247
|
+
|
251
248
|
props['parent_paths'] = {}
|
252
|
-
if !props['parent']
|
253
|
-
|
254
|
-
end
|
249
|
+
next if !props['parent']
|
250
|
+
|
255
251
|
parent = objs[props['parent']]
|
256
252
|
props['paths'].keys.each do |type|
|
257
253
|
props['parent_paths'][type] = parent['paths'][type]
|
@@ -259,17 +255,15 @@ class PerfAggregator
|
|
259
255
|
parent['children'] << obj
|
260
256
|
end
|
261
257
|
end
|
262
|
-
|
258
|
+
|
263
259
|
def _aggregate_metrics vms_stats, perf_metrics
|
264
|
-
out = Hash[perf_metrics.keys.map{|x| [x, 0]}]
|
265
|
-
avg_counter = Hash[perf_metrics.keys.map{|x| [x, 0]}]
|
266
|
-
|
260
|
+
out = Hash[perf_metrics.keys.map{ |x| [x, 0] }]
|
261
|
+
avg_counter = Hash[perf_metrics.keys.map{ |x| [x, 0] }]
|
262
|
+
|
267
263
|
vms_stats.each do |vm_stats|
|
268
264
|
perf_metrics.each do |key, type|
|
269
265
|
values = vm_stats[key]
|
270
|
-
if !values.is_a?(Array)
|
271
|
-
values = [values]
|
272
|
-
end
|
266
|
+
values = [values] if !values.is_a?(Array)
|
273
267
|
values.compact.each do |val|
|
274
268
|
if type == :sum
|
275
269
|
out[key] += val
|
@@ -287,25 +281,23 @@ class PerfAggregator
|
|
287
281
|
end
|
288
282
|
end
|
289
283
|
end
|
290
|
-
|
284
|
+
|
291
285
|
perf_metrics.each do |key, type|
|
292
286
|
if type == :avg_ignore_zero || type == :avg
|
293
|
-
if avg_counter[key] > 0
|
294
|
-
out[key] = out[key] / avg_counter[key]
|
295
|
-
end
|
287
|
+
out[key] = out[key] / avg_counter[key] if avg_counter[key] > 0
|
296
288
|
end
|
297
289
|
end
|
298
|
-
|
290
|
+
|
299
291
|
out
|
300
292
|
end
|
301
|
-
|
293
|
+
|
302
294
|
def _collect_info_on_all_vms_single root_folder, opts = {}
|
303
295
|
prop_names = opts[:prop_names]
|
304
296
|
if !prop_names
|
305
297
|
prop_names = [
|
306
298
|
'name',
|
307
299
|
'config.template',
|
308
|
-
'runtime.powerState', 'datastore', 'config.annotation',
|
300
|
+
'runtime.powerState', 'datastore', 'config.annotation',
|
309
301
|
'parent', 'resourcePool', 'storage.perDatastoreUsage',
|
310
302
|
'summary.config.memorySizeMB',
|
311
303
|
'summary.config.numCpu',
|
@@ -320,9 +312,9 @@ class PerfAggregator
|
|
320
312
|
perf_metrics = opts[:perf_metrics]
|
321
313
|
if !perf_metrics
|
322
314
|
perf_metrics = {
|
323
|
-
'virtualDisk.read' => :avg,
|
315
|
+
'virtualDisk.read' => :avg,
|
324
316
|
'virtualDisk.write' => :avg,
|
325
|
-
'virtualDisk.numberReadAveraged' => :avg,
|
317
|
+
'virtualDisk.numberReadAveraged' => :avg,
|
326
318
|
'virtualDisk.numberWriteAveraged' => :avg,
|
327
319
|
'virtualDisk.totalReadLatency' => :avg_ignore_zero,
|
328
320
|
'virtualDisk.totalWriteLatency' => :avg_ignore_zero,
|
@@ -331,36 +323,36 @@ class PerfAggregator
|
|
331
323
|
host_perf_metrics = opts[:host_perf_metrics]
|
332
324
|
if !host_perf_metrics
|
333
325
|
host_perf_metrics = {
|
334
|
-
'cpu.usage' => :avg,
|
326
|
+
'cpu.usage' => :avg,
|
335
327
|
'mem.usage' => :avg,
|
336
328
|
}
|
337
329
|
end
|
338
330
|
|
339
331
|
vms_props, inventory = all_inventory_flat root_folder, prop_names
|
340
332
|
vms = vms_props.keys
|
341
|
-
|
342
|
-
hosts_props = inventory.select{|k, v| k.is_a?(RbVmomi::VIM::HostSystem)}
|
333
|
+
|
334
|
+
hosts_props = inventory.select{ |k, v| k.is_a?(RbVmomi::VIM::HostSystem) }
|
343
335
|
|
344
336
|
conn = root_folder._connection
|
345
337
|
sc = conn.serviceContent
|
346
338
|
pc = sc.propertyCollector
|
347
339
|
pm = sc.perfManager
|
348
340
|
vc_uuid = conn.instanceUuid
|
349
|
-
|
350
|
-
connected_vms = vms_props.select do |vm, props|
|
351
|
-
is_connected = props['runtime.connectionState'] !=
|
341
|
+
|
342
|
+
connected_vms = vms_props.select do |vm, props|
|
343
|
+
is_connected = props['runtime.connectionState'] != 'disconnected'
|
352
344
|
is_template = props['config.template']
|
353
345
|
is_connected && !is_template
|
354
346
|
end.keys
|
355
|
-
|
347
|
+
|
356
348
|
begin
|
357
349
|
# XXX: Need to find a good way to get the "right" samples
|
358
350
|
if connected_vms.length == 0
|
359
351
|
{}
|
360
352
|
else
|
361
353
|
vms_stats = pm.retrieve_stats(
|
362
|
-
connected_vms, perf_metrics.keys,
|
363
|
-
:
|
354
|
+
connected_vms, perf_metrics.keys,
|
355
|
+
max_samples: 3
|
364
356
|
)
|
365
357
|
end
|
366
358
|
rescue RbVmomi::Fault => ex
|
@@ -371,34 +363,31 @@ class PerfAggregator
|
|
371
363
|
raise
|
372
364
|
end
|
373
365
|
|
374
|
-
connected_hosts = hosts_props.select do |k,v|
|
375
|
-
v['runtime.connectionState'] !=
|
366
|
+
connected_hosts = hosts_props.select do |k, v|
|
367
|
+
v['runtime.connectionState'] != 'disconnected'
|
376
368
|
end
|
377
369
|
if connected_hosts.length > 0
|
378
370
|
hosts_stats = pm.retrieve_stats(
|
379
|
-
connected_hosts.keys, host_perf_metrics.keys,
|
380
|
-
:
|
371
|
+
connected_hosts.keys, host_perf_metrics.keys,
|
372
|
+
max_samples: 3
|
381
373
|
)
|
382
374
|
end
|
383
375
|
hosts_props.each do |host, props|
|
384
|
-
if !connected_hosts[host]
|
385
|
-
|
386
|
-
end
|
387
|
-
|
376
|
+
next if !connected_hosts[host]
|
377
|
+
|
388
378
|
stats = hosts_stats[host] || {}
|
389
379
|
stats = stats[:metrics] || {}
|
390
380
|
stats = _aggregate_metrics [stats], host_perf_metrics
|
391
381
|
props.merge!(stats)
|
392
382
|
end
|
393
|
-
|
383
|
+
|
394
384
|
vms_props.each do |vm, props|
|
395
|
-
if !connected_vms.member?(vm)
|
396
|
-
|
397
|
-
end
|
385
|
+
next if !connected_vms.member?(vm)
|
386
|
+
|
398
387
|
props['num.vm'] = 1
|
399
388
|
powered_on = (props['runtime.powerState'] == 'poweredOn')
|
400
389
|
props['num.poweredonvm'] = powered_on ? 1 : 0
|
401
|
-
|
390
|
+
|
402
391
|
stats = vms_stats[vm] || {}
|
403
392
|
stats = stats[:metrics] || {}
|
404
393
|
stats = _aggregate_metrics [stats], perf_metrics
|
@@ -411,51 +400,45 @@ class PerfAggregator
|
|
411
400
|
props.delete('virtualDisk.totalWriteLatency')
|
412
401
|
|
413
402
|
per_ds_usage = props['storage.perDatastoreUsage']
|
414
|
-
props['storage.space.committed'] = per_ds_usage.map{|x| x.committed}.inject(0, &:+)
|
415
|
-
props['storage.space.uncommitted'] = per_ds_usage.map{|x| x.uncommitted}.inject(0, &:+)
|
416
|
-
props['storage.space.unshared'] = per_ds_usage.map{|x| x.unshared}.inject(0, &:+)
|
403
|
+
props['storage.space.committed'] = per_ds_usage.map{ |x| x.committed }.inject(0, &:+)
|
404
|
+
props['storage.space.uncommitted'] = per_ds_usage.map{ |x| x.uncommitted }.inject(0, &:+)
|
405
|
+
props['storage.space.unshared'] = per_ds_usage.map{ |x| x.unshared }.inject(0, &:+)
|
417
406
|
|
418
407
|
props['parent_paths'] = {}
|
419
|
-
if inventory[props['parent']]
|
420
|
-
props['parent_paths']['vmfolder'] = inventory[props['parent']]['path']
|
421
|
-
end
|
408
|
+
props['parent_paths']['vmfolder'] = inventory[props['parent']]['path'] if inventory[props['parent']]
|
422
409
|
if !props['config.template']
|
423
410
|
rp_props = inventory[props['resourcePool']]
|
424
411
|
props['parent_paths']['rp'] = rp_props['path']
|
425
412
|
end
|
426
|
-
|
413
|
+
|
427
414
|
props['annotation_yaml'] = YAML.load(props['config.annotation'] || '')
|
428
|
-
if !props['annotation_yaml'].is_a?(Hash)
|
429
|
-
|
430
|
-
end
|
431
|
-
|
415
|
+
props['annotation_yaml'] = {} if !props['annotation_yaml'].is_a?(Hash)
|
416
|
+
|
432
417
|
props['customValue'] = Hash[props['customValue'].map do |x|
|
433
418
|
[x.key, x.value]
|
434
419
|
end]
|
435
|
-
|
420
|
+
|
436
421
|
props['vc_uuid'] = vc_uuid
|
437
422
|
end
|
438
|
-
|
439
|
-
[vms_props, inventory, hosts_props]
|
423
|
+
|
424
|
+
[vms_props, inventory, hosts_props]
|
440
425
|
end
|
441
|
-
|
426
|
+
|
442
427
|
def collect_info_on_all_vms root_folders, opts = {}
|
443
|
-
log
|
428
|
+
log 'Fetching information from all VCs ...'
|
444
429
|
vms_props = {}
|
445
430
|
hosts_props = {}
|
446
431
|
inventory = {}
|
447
432
|
lock = Mutex.new
|
448
433
|
root_folders.map do |root_folder|
|
449
|
-
Thread.new do
|
434
|
+
Thread.new do
|
450
435
|
begin
|
451
|
-
single_vms_props, single_inventory, single_hosts_props =
|
436
|
+
single_vms_props, single_inventory, single_hosts_props =
|
452
437
|
_collect_info_on_all_vms_single(root_folder, opts)
|
453
|
-
|
454
|
-
lock.synchronize do
|
438
|
+
|
439
|
+
lock.synchronize do
|
455
440
|
vms_props.merge!(single_vms_props)
|
456
|
-
if inventory['root']
|
457
|
-
single_inventory['root']['children'] += inventory['root']['children']
|
458
|
-
end
|
441
|
+
single_inventory['root']['children'] += inventory['root']['children'] if inventory['root']
|
459
442
|
inventory.merge!(single_inventory)
|
460
443
|
hosts_props.merge!(single_hosts_props)
|
461
444
|
end
|
@@ -467,69 +450,57 @@ class PerfAggregator
|
|
467
450
|
raise
|
468
451
|
end
|
469
452
|
end
|
470
|
-
end.each{|t| t.join}
|
453
|
+
end.each{ |t| t.join }
|
471
454
|
|
472
|
-
log
|
455
|
+
log 'Make data marshal friendly ...'
|
473
456
|
inventory = _make_marshal_friendly(inventory)
|
474
457
|
vms_props = _make_marshal_friendly(vms_props)
|
475
458
|
hosts_props = _make_marshal_friendly(hosts_props)
|
476
459
|
|
477
|
-
log
|
478
|
-
if @vm_processing_callback
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
log "Perform data aggregation ..."
|
483
|
-
# Processing the annotations may have added new nodes to the
|
460
|
+
log 'Perform external post processing ...'
|
461
|
+
@vm_processing_callback.call(self, vms_props, inventory) if @vm_processing_callback
|
462
|
+
|
463
|
+
log 'Perform data aggregation ...'
|
464
|
+
# Processing the annotations may have added new nodes to the
|
484
465
|
# inventory list, hence we need to run _compute_parents_and_children
|
485
466
|
# again to calculate the parents and children for the newly
|
486
467
|
# added nodes.
|
487
468
|
_compute_parents_and_children inventory
|
488
469
|
|
489
470
|
# Now that we have all VMs and a proper inventory tree built, we can
|
490
|
-
# aggregate the VM stats along all trees and tree nodes. This
|
471
|
+
# aggregate the VM stats along all trees and tree nodes. This
|
491
472
|
# de-normalizes the data heavily, but thats fine
|
492
473
|
path_types = opts[:path_types] || @path_types
|
493
474
|
inventory = _aggregate_vms path_types, vms_props, inventory
|
494
|
-
|
495
|
-
log
|
475
|
+
|
476
|
+
log 'Done collecting and aggregating stats'
|
496
477
|
|
497
478
|
@inventory = inventory
|
498
479
|
@vms_props = vms_props
|
499
|
-
|
480
|
+
|
500
481
|
{
|
501
|
-
'inventory' => inventory,
|
502
|
-
'vms_props' => vms_props,
|
482
|
+
'inventory' => inventory,
|
483
|
+
'vms_props' => vms_props,
|
503
484
|
'hosts_props' => hosts_props,
|
504
485
|
}
|
505
486
|
end
|
506
|
-
|
487
|
+
|
507
488
|
def _make_marshal_friendly hash
|
508
489
|
hash = Hash[hash.map do |k, v|
|
509
|
-
if v['parent']
|
510
|
-
|
511
|
-
|
512
|
-
if v['
|
513
|
-
|
514
|
-
end
|
515
|
-
if v['children']
|
516
|
-
v['children'] = v['children'].map{|x| _mo2str(x)}
|
517
|
-
end
|
518
|
-
if v['parents']
|
519
|
-
v['parents'] = v['parents'].map{|x| _mo2str(x)}
|
520
|
-
end
|
521
|
-
if v['datastore']
|
522
|
-
v['datastore'] = v['datastore'].map{|x| _mo2str(x)}
|
523
|
-
end
|
490
|
+
v['parent'] = _mo2str(v['parent']) if v['parent']
|
491
|
+
v['resourcePool'] = _mo2str(v['resourcePool']) if v['resourcePool']
|
492
|
+
v['children'] = v['children'].map{ |x| _mo2str(x) } if v['children']
|
493
|
+
v['parents'] = v['parents'].map{ |x| _mo2str(x) } if v['parents']
|
494
|
+
v['datastore'] = v['datastore'].map{ |x| _mo2str(x) } if v['datastore']
|
524
495
|
v['type'] = k.class.name
|
525
496
|
[_mo2str(k), v]
|
526
|
-
end]
|
527
|
-
# Marhsal hash to JSON and back. This is just debug code to ensure
|
528
|
-
# that all further processing can be done on a serialized dump of
|
497
|
+
end]
|
498
|
+
# Marhsal hash to JSON and back. This is just debug code to ensure
|
499
|
+
# that all further processing can be done on a serialized dump of
|
529
500
|
# the data.
|
530
501
|
hash = JSON.load(JSON.dump(hash))
|
531
502
|
end
|
532
|
-
|
503
|
+
|
533
504
|
def _mo2str mo
|
534
505
|
if !mo.is_a?(RbVmomi::VIM::ManagedObject)
|
535
506
|
mo
|
@@ -537,8 +508,8 @@ class PerfAggregator
|
|
537
508
|
"vim-#{mo._connection.instanceUuid}-#{mo._ref}"
|
538
509
|
end
|
539
510
|
end
|
540
|
-
|
541
|
-
# Helper method that aggregates the VM stats along all trees and
|
511
|
+
|
512
|
+
# Helper method that aggregates the VM stats along all trees and
|
542
513
|
# tree nodes. This de-normalizes the data heavily, but thats fine.
|
543
514
|
def _aggregate_vms path_types, vms_props, inventory
|
544
515
|
# XXX: Opimtization:
|
@@ -555,18 +526,17 @@ class PerfAggregator
|
|
555
526
|
reverse_index[path] = k
|
556
527
|
end
|
557
528
|
end
|
558
|
-
|
529
|
+
|
559
530
|
paths_vms = {}
|
560
|
-
|
531
|
+
|
561
532
|
vms_props.each do |vm, props|
|
562
|
-
if !props['parent_paths'] || !props['parent_paths'][path_type]
|
563
|
-
|
564
|
-
end
|
533
|
+
next if !props['parent_paths'] || !props['parent_paths'][path_type]
|
534
|
+
|
565
535
|
parent_path = props['parent_paths'][path_type]
|
566
536
|
while parent_path
|
567
537
|
parent = index[parent_path]
|
568
538
|
if !parent
|
569
|
-
puts
|
539
|
+
puts 'Parent is nil, so dumping some stuff'
|
570
540
|
puts path_type
|
571
541
|
puts "parent path: #{parent_path}"
|
572
542
|
pp index.keys
|
@@ -577,22 +547,22 @@ class PerfAggregator
|
|
577
547
|
parent_path = parent['parent_paths'][path_type]
|
578
548
|
end
|
579
549
|
end
|
580
|
-
|
550
|
+
|
581
551
|
paths_vms.each do |k, vms|
|
582
552
|
inventory[reverse_index[k]]['vms'] ||= {}
|
583
553
|
inventory[reverse_index[k]]['vms'][path_type] = vms
|
584
|
-
vms_stats = vms_props.select{|k, v| vms.member?(k)}.values
|
554
|
+
vms_stats = vms_props.select{ |k, v| vms.member?(k) }.values
|
585
555
|
stats = _aggregate_metrics vms_stats, @perf_metrics
|
586
556
|
inventory[reverse_index[k]]['stats'] ||= {}
|
587
557
|
inventory[reverse_index[k]]['stats'][path_type] = stats
|
588
558
|
end
|
589
|
-
|
559
|
+
|
590
560
|
#pp paths_vms.map{|k, v| [k, reverse_index[k], v.length, index[k]['stats'][path_type].length]}
|
591
561
|
end
|
592
|
-
|
562
|
+
|
593
563
|
inventory
|
594
564
|
end
|
595
|
-
|
565
|
+
|
596
566
|
def visualize_vm_props
|
597
567
|
path_types_rows = construct_tree_rows_from_vm_props
|
598
568
|
path_types_rows.each do |path_type, rows|
|
@@ -601,7 +571,7 @@ class PerfAggregator
|
|
601
571
|
indent, name, stats = row
|
602
572
|
puts "#{' ' * indent}#{name}: #{stats['num.vm']}"
|
603
573
|
end
|
604
|
-
puts
|
574
|
+
puts ''
|
605
575
|
end
|
606
576
|
end
|
607
577
|
|
@@ -621,9 +591,9 @@ class PerfAggregator
|
|
621
591
|
end
|
622
592
|
rows
|
623
593
|
end
|
624
|
-
|
594
|
+
|
625
595
|
Hash[path_types.map do |path_type|
|
626
|
-
key, root = @inventory.find{|k, v| v['paths'][path_type] == 'root'}
|
596
|
+
key, root = @inventory.find{ |k, v| v['paths'][path_type] == 'root' }
|
627
597
|
rows = visualize_node path_type, root, @inventory
|
628
598
|
[path_type, rows]
|
629
599
|
end]
|