vmpooler 2.0.0 → 2.3.0
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/lib/vmpooler/api/helpers.rb +365 -294
- data/lib/vmpooler/api/reroute.rb +16 -0
- data/lib/vmpooler/api/v1.rb +500 -377
- data/lib/vmpooler/api/v2.rb +429 -0
- data/lib/vmpooler/api.rb +2 -1
- data/lib/vmpooler/pool_manager.rb +105 -88
- data/lib/vmpooler/providers/base.rb +26 -3
- data/lib/vmpooler/util/parsing.rb +21 -1
- data/lib/vmpooler/version.rb +1 -1
- data/lib/vmpooler.rb +11 -3
- metadata +82 -48
data/lib/vmpooler/api/helpers.rb
CHANGED
@@ -6,136 +6,170 @@ module Vmpooler
|
|
6
6
|
|
7
7
|
module Helpers
|
8
8
|
|
9
|
+
def tracer
|
10
|
+
@tracer ||= OpenTelemetry.tracer_provider.tracer('api', Vmpooler::VERSION)
|
11
|
+
end
|
12
|
+
|
9
13
|
def has_token?
|
10
14
|
request.env['HTTP_X_AUTH_TOKEN'].nil? ? false : true
|
11
15
|
end
|
12
16
|
|
13
17
|
def valid_token?(backend)
|
14
|
-
|
18
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
19
|
+
return false unless has_token?
|
15
20
|
|
16
|
-
|
21
|
+
backend.exists?("vmpooler__token__#{request.env['HTTP_X_AUTH_TOKEN']}") ? true : false
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
def validate_token(backend)
|
20
|
-
|
21
|
-
backend
|
26
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
27
|
+
if valid_token?(backend)
|
28
|
+
backend.hset("vmpooler__token__#{request.env['HTTP_X_AUTH_TOKEN']}", 'last', Time.now)
|
22
29
|
|
23
|
-
|
24
|
-
|
30
|
+
return true
|
31
|
+
end
|
25
32
|
|
26
|
-
|
33
|
+
content_type :json
|
27
34
|
|
28
|
-
|
35
|
+
result = { 'ok' => false }
|
29
36
|
|
30
|
-
|
31
|
-
|
37
|
+
headers['WWW-Authenticate'] = 'Basic realm="Authentication required"'
|
38
|
+
halt 401, JSON.pretty_generate(result)
|
39
|
+
end
|
32
40
|
end
|
33
41
|
|
34
42
|
def validate_auth(backend)
|
35
|
-
|
43
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
44
|
+
return if authorized?
|
36
45
|
|
37
|
-
|
46
|
+
content_type :json
|
38
47
|
|
39
|
-
|
48
|
+
result = { 'ok' => false }
|
40
49
|
|
41
|
-
|
42
|
-
|
50
|
+
headers['WWW-Authenticate'] = 'Basic realm="Authentication required"'
|
51
|
+
halt 401, JSON.pretty_generate(result)
|
52
|
+
end
|
43
53
|
end
|
44
54
|
|
45
55
|
def authorized?
|
46
|
-
|
56
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
57
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
47
58
|
|
48
|
-
|
49
|
-
|
59
|
+
if @auth.provided? and @auth.basic? and @auth.credentials
|
60
|
+
username, password = @auth.credentials
|
50
61
|
|
51
|
-
|
52
|
-
|
62
|
+
if authenticate(Vmpooler::API.settings.config[:auth], username, password)
|
63
|
+
return true
|
64
|
+
end
|
53
65
|
end
|
54
|
-
end
|
55
66
|
|
56
|
-
|
67
|
+
return false
|
68
|
+
end
|
57
69
|
end
|
58
70
|
|
59
71
|
def authenticate_ldap(port, host, encryption_hash, user_object, base, username_str, password_str)
|
60
|
-
|
61
|
-
|
62
|
-
:
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
72
|
+
tracer.in_span(
|
73
|
+
"Vmpooler::API::Helpers.#{__method__}",
|
74
|
+
attributes: {
|
75
|
+
'net.peer.name' => host,
|
76
|
+
'net.peer.port' => port,
|
77
|
+
'net.transport' => 'ip_tcp',
|
78
|
+
'enduser.id' => username_str
|
79
|
+
},
|
80
|
+
kind: :client
|
81
|
+
) do
|
82
|
+
ldap = Net::LDAP.new(
|
83
|
+
:host => host,
|
84
|
+
:port => port,
|
85
|
+
:encryption => encryption_hash,
|
86
|
+
:base => base,
|
87
|
+
:auth => {
|
88
|
+
:method => :simple,
|
89
|
+
:username => "#{user_object}=#{username_str},#{base}",
|
90
|
+
:password => password_str
|
91
|
+
}
|
92
|
+
)
|
71
93
|
|
72
|
-
|
94
|
+
return true if ldap.bind
|
73
95
|
|
74
|
-
|
96
|
+
return false
|
97
|
+
end
|
75
98
|
end
|
76
99
|
|
77
100
|
def authenticate(auth, username_str, password_str)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
ldap_base = auth[:ldap]['base']
|
83
|
-
ldap_port = auth[:ldap]['port'] || 389
|
84
|
-
ldap_user_obj = auth[:ldap]['user_object']
|
85
|
-
ldap_host = auth[:ldap]['host']
|
86
|
-
ldap_encryption_hash = auth[:ldap]['encryption'] || {
|
87
|
-
:method => :start_tls,
|
88
|
-
:tls_options => { :ssl_version => 'TLSv1' }
|
101
|
+
tracer.in_span(
|
102
|
+
"Vmpooler::API::Helpers.#{__method__}",
|
103
|
+
attributes: {
|
104
|
+
'enduser.id' => username_str
|
89
105
|
}
|
106
|
+
) do
|
107
|
+
case auth['provider']
|
108
|
+
when 'dummy'
|
109
|
+
return (username_str != password_str)
|
110
|
+
when 'ldap'
|
111
|
+
ldap_base = auth[:ldap]['base']
|
112
|
+
ldap_port = auth[:ldap]['port'] || 389
|
113
|
+
ldap_user_obj = auth[:ldap]['user_object']
|
114
|
+
ldap_host = auth[:ldap]['host']
|
115
|
+
ldap_encryption_hash = auth[:ldap]['encryption'] || {
|
116
|
+
:method => :start_tls,
|
117
|
+
:tls_options => { :ssl_version => 'TLSv1' }
|
118
|
+
}
|
90
119
|
|
91
|
-
|
92
|
-
|
93
|
-
|
120
|
+
unless ldap_base.is_a? Array
|
121
|
+
ldap_base = ldap_base.split
|
122
|
+
end
|
94
123
|
|
95
|
-
|
96
|
-
|
97
|
-
|
124
|
+
unless ldap_user_obj.is_a? Array
|
125
|
+
ldap_user_obj = ldap_user_obj.split
|
126
|
+
end
|
98
127
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
128
|
+
ldap_base.each do |search_base|
|
129
|
+
ldap_user_obj.each do |search_user_obj|
|
130
|
+
result = authenticate_ldap(
|
131
|
+
ldap_port,
|
132
|
+
ldap_host,
|
133
|
+
ldap_encryption_hash,
|
134
|
+
search_user_obj,
|
135
|
+
search_base,
|
136
|
+
username_str,
|
137
|
+
password_str
|
138
|
+
)
|
139
|
+
return true if result
|
140
|
+
end
|
111
141
|
end
|
112
|
-
end
|
113
142
|
|
114
|
-
|
143
|
+
return false
|
144
|
+
end
|
115
145
|
end
|
116
146
|
end
|
117
147
|
|
118
148
|
def export_tags(backend, hostname, tags)
|
119
|
-
|
120
|
-
|
121
|
-
|
149
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
150
|
+
backend.pipelined do |pipeline|
|
151
|
+
tags.each_pair do |tag, value|
|
152
|
+
next if value.nil? or value.empty?
|
122
153
|
|
123
|
-
|
124
|
-
|
154
|
+
pipeline.hset("vmpooler__vm__#{hostname}", "tag:#{tag}", value)
|
155
|
+
pipeline.hset("vmpooler__tag__#{Date.today}", "#{hostname}:#{tag}", value)
|
156
|
+
end
|
125
157
|
end
|
126
158
|
end
|
127
159
|
end
|
128
160
|
|
129
161
|
def filter_tags(tags)
|
130
|
-
|
162
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
163
|
+
return unless Vmpooler::API.settings.config[:tagfilter]
|
131
164
|
|
132
|
-
|
133
|
-
|
165
|
+
tags.each_pair do |tag, value|
|
166
|
+
next unless filter = Vmpooler::API.settings.config[:tagfilter][tag]
|
134
167
|
|
135
|
-
|
136
|
-
|
168
|
+
tags[tag] = value.match(filter).captures.join if value.match(filter)
|
169
|
+
end
|
137
170
|
|
138
|
-
|
171
|
+
tags
|
172
|
+
end
|
139
173
|
end
|
140
174
|
|
141
175
|
def mean(list)
|
@@ -150,307 +184,329 @@ module Vmpooler
|
|
150
184
|
def hostname_shorten(hostname, domain=nil)
|
151
185
|
if domain && hostname =~ /^[\w-]+\.#{domain}$/
|
152
186
|
hostname = hostname[/[^.]+/]
|
187
|
+
elsif hostname =~ /^[\w-]+\..+$/
|
188
|
+
hostname = hostname[/[^.]+/]
|
153
189
|
end
|
154
190
|
|
155
191
|
hostname
|
156
192
|
end
|
157
193
|
|
158
194
|
def get_task_times(backend, task, date_str)
|
159
|
-
|
195
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
196
|
+
backend.hvals("vmpooler__#{task}__" + date_str).map(&:to_f)
|
197
|
+
end
|
160
198
|
end
|
161
199
|
|
162
200
|
# Takes the pools and a key to run scard on
|
163
201
|
# returns an integer for the total count
|
164
202
|
def get_total_across_pools_redis_scard(pools, key, backend)
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
203
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
204
|
+
# using pipelined is much faster than querying each of the pools and adding them
|
205
|
+
# as we get the result.
|
206
|
+
res = backend.pipelined do |pipeline|
|
207
|
+
pools.each do |pool|
|
208
|
+
pipeline.scard(key + pool['name'])
|
209
|
+
end
|
170
210
|
end
|
211
|
+
res.inject(0) { |m, x| m + x }.to_i
|
171
212
|
end
|
172
|
-
res.inject(0) { |m, x| m + x }.to_i
|
173
213
|
end
|
174
214
|
|
175
215
|
# Takes the pools and a key to run scard on
|
176
216
|
# returns a hash with each pool name as key and the value being the count as integer
|
177
217
|
def get_list_across_pools_redis_scard(pools, key, backend)
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
218
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
219
|
+
# using pipelined is much faster than querying each of the pools and adding them
|
220
|
+
# as we get the result.
|
221
|
+
temp_hash = {}
|
222
|
+
res = backend.pipelined do |pipeline|
|
223
|
+
pools.each do |pool|
|
224
|
+
pipeline.scard(key + pool['name'])
|
225
|
+
end
|
184
226
|
end
|
227
|
+
pools.each_with_index do |pool, i|
|
228
|
+
temp_hash[pool['name']] = res[i].to_i
|
229
|
+
end
|
230
|
+
temp_hash
|
185
231
|
end
|
186
|
-
pools.each_with_index do |pool, i|
|
187
|
-
temp_hash[pool['name']] = res[i].to_i
|
188
|
-
end
|
189
|
-
temp_hash
|
190
232
|
end
|
191
233
|
|
192
234
|
# Takes the pools and a key to run hget on
|
193
235
|
# returns a hash with each pool name as key and the value as string
|
194
236
|
def get_list_across_pools_redis_hget(pools, key, backend)
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
237
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
238
|
+
# using pipelined is much faster than querying each of the pools and adding them
|
239
|
+
# as we get the result.
|
240
|
+
temp_hash = {}
|
241
|
+
res = backend.pipelined do |pipeline|
|
242
|
+
pools.each do |pool|
|
243
|
+
pipeline.hget(key, pool['name'])
|
244
|
+
end
|
201
245
|
end
|
246
|
+
pools.each_with_index do |pool, i|
|
247
|
+
temp_hash[pool['name']] = res[i].to_s
|
248
|
+
end
|
249
|
+
temp_hash
|
202
250
|
end
|
203
|
-
pools.each_with_index do |pool, i|
|
204
|
-
temp_hash[pool['name']] = res[i].to_s
|
205
|
-
end
|
206
|
-
temp_hash
|
207
251
|
end
|
208
252
|
|
209
253
|
def get_capacity_metrics(pools, backend)
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
254
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
255
|
+
capacity = {
|
256
|
+
current: 0,
|
257
|
+
total: 0,
|
258
|
+
percent: 0
|
259
|
+
}
|
215
260
|
|
216
|
-
|
217
|
-
|
218
|
-
|
261
|
+
pools.each do |pool|
|
262
|
+
capacity[:total] += pool['size'].to_i
|
263
|
+
end
|
219
264
|
|
220
|
-
|
265
|
+
capacity[:current] = get_total_across_pools_redis_scard(pools, 'vmpooler__ready__', backend)
|
221
266
|
|
222
|
-
|
223
|
-
|
224
|
-
|
267
|
+
if capacity[:total] > 0
|
268
|
+
capacity[:percent] = (capacity[:current].fdiv(capacity[:total]) * 100.0).round(1)
|
269
|
+
end
|
225
270
|
|
226
|
-
|
271
|
+
capacity
|
272
|
+
end
|
227
273
|
end
|
228
274
|
|
229
275
|
def get_queue_metrics(pools, backend)
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
276
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
277
|
+
queue = {
|
278
|
+
pending: 0,
|
279
|
+
cloning: 0,
|
280
|
+
booting: 0,
|
281
|
+
ready: 0,
|
282
|
+
running: 0,
|
283
|
+
completed: 0,
|
284
|
+
total: 0
|
285
|
+
}
|
286
|
+
|
287
|
+
queue[:pending] = get_total_across_pools_redis_scard(pools, 'vmpooler__pending__', backend)
|
288
|
+
queue[:ready] = get_total_across_pools_redis_scard(pools, 'vmpooler__ready__', backend)
|
289
|
+
queue[:running] = get_total_across_pools_redis_scard(pools, 'vmpooler__running__', backend)
|
290
|
+
queue[:completed] = get_total_across_pools_redis_scard(pools, 'vmpooler__completed__', backend)
|
291
|
+
|
292
|
+
queue[:cloning] = backend.get('vmpooler__tasks__clone').to_i + backend.get('vmpooler__tasks__ondemandclone').to_i
|
293
|
+
queue[:booting] = queue[:pending].to_i - queue[:cloning].to_i
|
294
|
+
queue[:booting] = 0 if queue[:booting] < 0
|
295
|
+
queue[:total] = queue[:pending].to_i + queue[:ready].to_i + queue[:running].to_i + queue[:completed].to_i
|
296
|
+
|
297
|
+
queue
|
298
|
+
end
|
251
299
|
end
|
252
300
|
|
253
301
|
def get_tag_metrics(backend, date_str, opts = {})
|
254
|
-
|
302
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
303
|
+
opts = {:only => false}.merge(opts)
|
255
304
|
|
256
|
-
|
305
|
+
tags = {}
|
257
306
|
|
258
|
-
|
259
|
-
|
260
|
-
|
307
|
+
backend.hgetall("vmpooler__tag__#{date_str}").each do |key, value|
|
308
|
+
hostname = 'unknown'
|
309
|
+
tag = 'unknown'
|
261
310
|
|
262
|
-
|
263
|
-
|
264
|
-
|
311
|
+
if key =~ /:/
|
312
|
+
hostname, tag = key.split(':', 2)
|
313
|
+
end
|
265
314
|
|
266
|
-
|
315
|
+
next if opts[:only] && tag != opts[:only]
|
267
316
|
|
268
|
-
|
269
|
-
|
270
|
-
|
317
|
+
tags[tag] ||= {}
|
318
|
+
tags[tag][value] ||= 0
|
319
|
+
tags[tag][value] += 1
|
271
320
|
|
272
|
-
|
273
|
-
|
274
|
-
|
321
|
+
tags[tag]['total'] ||= 0
|
322
|
+
tags[tag]['total'] += 1
|
323
|
+
end
|
275
324
|
|
276
|
-
|
325
|
+
tags
|
326
|
+
end
|
277
327
|
end
|
278
328
|
|
279
329
|
def get_tag_summary(backend, from_date, to_date, opts = {})
|
280
|
-
|
281
|
-
|
282
|
-
result = {
|
283
|
-
tag: {},
|
284
|
-
daily: []
|
285
|
-
}
|
330
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
331
|
+
opts = {:only => false}.merge(opts)
|
286
332
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
tag: get_tag_metrics(backend, date.to_s, opts)
|
333
|
+
result = {
|
334
|
+
tag: {},
|
335
|
+
daily: []
|
291
336
|
}
|
292
|
-
result[:daily].push(daily)
|
293
|
-
end
|
294
337
|
|
295
|
-
|
296
|
-
|
297
|
-
|
338
|
+
(from_date..to_date).each do |date|
|
339
|
+
daily = {
|
340
|
+
date: date.to_s,
|
341
|
+
tag: get_tag_metrics(backend, date.to_s, opts)
|
342
|
+
}
|
343
|
+
result[:daily].push(daily)
|
344
|
+
end
|
345
|
+
|
346
|
+
result[:daily].each do |daily|
|
347
|
+
daily[:tag].each_key do |tag|
|
348
|
+
result[:tag][tag] ||= {}
|
298
349
|
|
299
|
-
|
300
|
-
|
301
|
-
|
350
|
+
daily[:tag][tag].each do |key, value|
|
351
|
+
result[:tag][tag][key] ||= 0
|
352
|
+
result[:tag][tag][key] += value
|
353
|
+
end
|
302
354
|
end
|
303
355
|
end
|
304
|
-
end
|
305
356
|
|
306
|
-
|
357
|
+
result
|
358
|
+
end
|
307
359
|
end
|
308
360
|
|
309
361
|
def get_task_metrics(backend, task_str, date_str, opts = {})
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
362
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
363
|
+
opts = {:bypool => false, :only => false}.merge(opts)
|
364
|
+
|
365
|
+
task = {
|
366
|
+
duration: {
|
367
|
+
average: 0,
|
368
|
+
min: 0,
|
369
|
+
max: 0,
|
370
|
+
total: 0
|
371
|
+
},
|
372
|
+
count: {
|
373
|
+
total: 0
|
374
|
+
}
|
375
|
+
}
|
323
376
|
|
324
|
-
|
377
|
+
task[:count][:total] = backend.hlen("vmpooler__#{task_str}__#{date_str}").to_i
|
325
378
|
|
326
|
-
|
327
|
-
|
328
|
-
|
379
|
+
if task[:count][:total] > 0
|
380
|
+
if opts[:bypool] == true
|
381
|
+
task_times_bypool = {}
|
329
382
|
|
330
|
-
|
331
|
-
|
383
|
+
task[:count][:pool] = {}
|
384
|
+
task[:duration][:pool] = {}
|
332
385
|
|
333
|
-
|
334
|
-
|
335
|
-
|
386
|
+
backend.hgetall("vmpooler__#{task_str}__#{date_str}").each do |key, value|
|
387
|
+
pool = 'unknown'
|
388
|
+
hostname = 'unknown'
|
336
389
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
390
|
+
if key =~ /:/
|
391
|
+
pool, hostname = key.split(':')
|
392
|
+
else
|
393
|
+
hostname = key
|
394
|
+
end
|
342
395
|
|
343
|
-
|
344
|
-
|
396
|
+
task[:count][:pool][pool] ||= {}
|
397
|
+
task[:duration][:pool][pool] ||= {}
|
345
398
|
|
346
|
-
|
347
|
-
|
348
|
-
|
399
|
+
task_times_bypool[pool] ||= []
|
400
|
+
task_times_bypool[pool].push(value.to_f)
|
401
|
+
end
|
349
402
|
|
350
|
-
|
351
|
-
|
403
|
+
task_times_bypool.each_key do |pool|
|
404
|
+
task[:count][:pool][pool][:total] = task_times_bypool[pool].length
|
352
405
|
|
353
|
-
|
354
|
-
|
355
|
-
|
406
|
+
task[:duration][:pool][pool][:total] = task_times_bypool[pool].reduce(:+).to_f
|
407
|
+
task[:duration][:pool][pool][:average] = (task[:duration][:pool][pool][:total] / task[:count][:pool][pool][:total]).round(1)
|
408
|
+
task[:duration][:pool][pool][:min], task[:duration][:pool][pool][:max] = task_times_bypool[pool].minmax
|
409
|
+
end
|
356
410
|
end
|
357
|
-
end
|
358
411
|
|
359
|
-
|
412
|
+
task_times = get_task_times(backend, task_str, date_str)
|
360
413
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
414
|
+
task[:duration][:total] = task_times.reduce(:+).to_f
|
415
|
+
task[:duration][:average] = (task[:duration][:total] / task[:count][:total]).round(1)
|
416
|
+
task[:duration][:min], task[:duration][:max] = task_times.minmax
|
417
|
+
end
|
365
418
|
|
366
|
-
|
367
|
-
|
368
|
-
|
419
|
+
if opts[:only]
|
420
|
+
task.each_key do |key|
|
421
|
+
task.delete(key) unless key.to_s == opts[:only]
|
422
|
+
end
|
369
423
|
end
|
370
|
-
end
|
371
424
|
|
372
|
-
|
425
|
+
task
|
426
|
+
end
|
373
427
|
end
|
374
428
|
|
375
429
|
def get_task_summary(backend, task_str, from_date, to_date, opts = {})
|
376
|
-
|
430
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
431
|
+
opts = {:bypool => false, :only => false}.merge(opts)
|
377
432
|
|
378
|
-
|
433
|
+
task_sym = task_str.to_sym
|
379
434
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
}
|
384
|
-
|
385
|
-
(from_date..to_date).each do |date|
|
386
|
-
daily = {
|
387
|
-
date: date.to_s,
|
388
|
-
task_sym => get_task_metrics(backend, task_str, date.to_s, opts)
|
435
|
+
result = {
|
436
|
+
task_sym => {},
|
437
|
+
daily: []
|
389
438
|
}
|
390
|
-
result[:daily].push(daily)
|
391
|
-
end
|
392
439
|
|
393
|
-
|
394
|
-
|
440
|
+
(from_date..to_date).each do |date|
|
441
|
+
daily = {
|
442
|
+
date: date.to_s,
|
443
|
+
task_sym => get_task_metrics(backend, task_str, date.to_s, opts)
|
444
|
+
}
|
445
|
+
result[:daily].push(daily)
|
446
|
+
end
|
395
447
|
|
396
|
-
|
397
|
-
|
398
|
-
result[task_sym][type] ||= {}
|
399
|
-
daily_task[type] ||= {}
|
448
|
+
daily_task = {}
|
449
|
+
daily_task_bypool = {} if opts[:bypool] == true
|
400
450
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
451
|
+
result[:daily].each do |daily|
|
452
|
+
daily[task_sym].each_key do |type|
|
453
|
+
result[task_sym][type] ||= {}
|
454
|
+
daily_task[type] ||= {}
|
455
|
+
|
456
|
+
['min', 'max'].each do |key|
|
457
|
+
if daily[task_sym][type][key]
|
458
|
+
daily_task[type][:data] ||= []
|
459
|
+
daily_task[type][:data].push(daily[task_sym][type][key])
|
460
|
+
end
|
405
461
|
end
|
406
|
-
end
|
407
462
|
|
408
|
-
|
409
|
-
|
463
|
+
result[task_sym][type][:total] ||= 0
|
464
|
+
result[task_sym][type][:total] += daily[task_sym][type][:total]
|
410
465
|
|
411
|
-
|
412
|
-
|
413
|
-
|
466
|
+
if opts[:bypool] == true
|
467
|
+
result[task_sym][type][:pool] ||= {}
|
468
|
+
daily_task_bypool[type] ||= {}
|
414
469
|
|
415
|
-
|
470
|
+
next unless daily[task_sym][type][:pool]
|
416
471
|
|
417
|
-
|
418
|
-
|
419
|
-
|
472
|
+
daily[task_sym][type][:pool].each_key do |pool|
|
473
|
+
result[task_sym][type][:pool][pool] ||= {}
|
474
|
+
daily_task_bypool[type][pool] ||= {}
|
420
475
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
476
|
+
['min', 'max'].each do |key|
|
477
|
+
if daily[task_sym][type][:pool][pool][key.to_sym]
|
478
|
+
daily_task_bypool[type][pool][:data] ||= []
|
479
|
+
daily_task_bypool[type][pool][:data].push(daily[task_sym][type][:pool][pool][key.to_sym])
|
480
|
+
end
|
425
481
|
end
|
426
|
-
end
|
427
482
|
|
428
|
-
|
429
|
-
|
483
|
+
result[task_sym][type][:pool][pool][:total] ||= 0
|
484
|
+
result[task_sym][type][:pool][pool][:total] += daily[task_sym][type][:pool][pool][:total]
|
485
|
+
end
|
430
486
|
end
|
431
487
|
end
|
432
488
|
end
|
433
|
-
end
|
434
489
|
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
490
|
+
result[task_sym].each_key do |type|
|
491
|
+
if daily_task[type][:data]
|
492
|
+
result[task_sym][type][:min], result[task_sym][type][:max] = daily_task[type][:data].minmax
|
493
|
+
result[task_sym][type][:average] = mean(daily_task[type][:data])
|
494
|
+
end
|
440
495
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
496
|
+
if opts[:bypool] == true
|
497
|
+
result[task_sym].each_key do |type|
|
498
|
+
result[task_sym][type][:pool].each_key do |pool|
|
499
|
+
if daily_task_bypool[type][pool][:data]
|
500
|
+
result[task_sym][type][:pool][pool][:min], result[task_sym][type][:pool][pool][:max] = daily_task_bypool[type][pool][:data].minmax
|
501
|
+
result[task_sym][type][:pool][pool][:average] = mean(daily_task_bypool[type][pool][:data])
|
502
|
+
end
|
447
503
|
end
|
448
504
|
end
|
449
505
|
end
|
450
506
|
end
|
451
|
-
end
|
452
507
|
|
453
|
-
|
508
|
+
result
|
509
|
+
end
|
454
510
|
end
|
455
511
|
|
456
512
|
def pool_index(pools)
|
@@ -464,11 +520,13 @@ module Vmpooler
|
|
464
520
|
end
|
465
521
|
|
466
522
|
def template_ready?(pool, backend)
|
467
|
-
|
468
|
-
|
469
|
-
|
523
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
524
|
+
prepared_template = backend.hget('vmpooler__template__prepared', pool['name'])
|
525
|
+
return false if prepared_template.nil?
|
526
|
+
return true if pool['template'] == prepared_template
|
470
527
|
|
471
|
-
|
528
|
+
return false
|
529
|
+
end
|
472
530
|
end
|
473
531
|
|
474
532
|
def is_integer?(x)
|
@@ -479,26 +537,39 @@ module Vmpooler
|
|
479
537
|
end
|
480
538
|
|
481
539
|
def open_socket(host, domain = nil, timeout = 1, port = 22, &_block)
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
540
|
+
tracer.in_span(
|
541
|
+
"Vmpooler::API::Helpers.#{__method__}",
|
542
|
+
attributes: {
|
543
|
+
'net.peer.port' => port,
|
544
|
+
'net.transport' => 'ip_tcp'
|
545
|
+
},
|
546
|
+
kind: :client
|
547
|
+
) do
|
548
|
+
Timeout.timeout(timeout) do
|
549
|
+
target_host = host
|
550
|
+
target_host = "#{host}.#{domain}" if domain
|
551
|
+
span = OpenTelemetry::Trace.current_span
|
552
|
+
span.set_attribute('net.peer.name', target_host)
|
553
|
+
sock = TCPSocket.new target_host, port
|
554
|
+
begin
|
555
|
+
yield sock if block_given?
|
556
|
+
ensure
|
557
|
+
sock.close
|
558
|
+
end
|
490
559
|
end
|
491
560
|
end
|
492
561
|
end
|
493
562
|
|
494
563
|
def vm_ready?(vm_name, domain = nil)
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
564
|
+
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
|
565
|
+
begin
|
566
|
+
open_socket(vm_name, domain)
|
567
|
+
rescue StandardError => _e
|
568
|
+
return false
|
569
|
+
end
|
500
570
|
|
501
|
-
|
571
|
+
true
|
572
|
+
end
|
502
573
|
end
|
503
574
|
end
|
504
575
|
end
|