vmpooler 0.10.3 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/vmpooler +2 -3
- data/lib/vmpooler.rb +20 -11
- data/lib/vmpooler/api.rb +2 -0
- data/lib/vmpooler/api/dashboard.rb +12 -5
- data/lib/vmpooler/api/helpers.rb +49 -44
- data/lib/vmpooler/api/reroute.rb +2 -0
- data/lib/vmpooler/api/v1.rb +58 -58
- data/lib/vmpooler/dashboard.rb +2 -1
- data/lib/vmpooler/dummy_statsd.rb +2 -0
- data/lib/vmpooler/generic_connection_pool.rb +8 -6
- data/lib/vmpooler/graphite.rb +5 -5
- data/lib/vmpooler/logger.rb +3 -1
- data/lib/vmpooler/pool_manager.rb +143 -126
- data/lib/vmpooler/providers.rb +13 -15
- data/lib/vmpooler/providers/base.rb +5 -3
- data/lib/vmpooler/providers/dummy.rb +16 -12
- data/lib/vmpooler/providers/vsphere.rb +118 -99
- data/lib/vmpooler/statsd.rb +9 -9
- data/lib/vmpooler/version.rb +3 -1
- metadata +14 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19dd8ce83614c49e92f13e043c2ee7865f1c664d92aa8f13e47fc328eb033690
|
4
|
+
data.tar.gz: c3618c9c13591b1b06748ac3e5d1c2dc7ba2eb9793ea2f3f014a762fd6deb4ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dcb8f8765f9c1fac52c2d0088aaa09a589b5145d5a81e901af614b8fcbbd588669b3f14e5c42f4d56d4681165f8814ef11b22073df6f97b85cef6fcb10d04e2
|
7
|
+
data.tar.gz: d7c917233daee973486a6a8add55222a92bb1708521caaefdf2666824c0785cebd1ce7e298448a66736bf7e0646f02a560067e54cc1d06a07ca6abae645898c9
|
data/bin/vmpooler
CHANGED
data/lib/vmpooler.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vmpooler
|
2
4
|
require 'date'
|
3
5
|
require 'json'
|
@@ -27,13 +29,21 @@ module Vmpooler
|
|
27
29
|
# Take the name of the config file either from an ENV variable or from the filepath argument
|
28
30
|
config_file = ENV['VMPOOLER_CONFIG_FILE'] || filepath
|
29
31
|
parsed_config = YAML.load_file(config_file) if File.exist? config_file
|
32
|
+
parsed_config[:config]['extra_config'] = ENV['EXTRA_CONFIG'] if ENV['EXTRA_CONFIG']
|
33
|
+
if parsed_config[:config]['extra_config']
|
34
|
+
extra_configs = parsed_config[:config]['extra_config'].split(',')
|
35
|
+
extra_configs.each do |config|
|
36
|
+
extra_config = YAML.load_file(config)
|
37
|
+
parsed_config.merge!(extra_config)
|
38
|
+
end
|
39
|
+
end
|
30
40
|
end
|
31
41
|
|
32
42
|
parsed_config ||= { config: {} }
|
33
43
|
|
34
44
|
# Bail out if someone attempts to start vmpooler with dummy authentication
|
35
45
|
# without enbaling debug mode.
|
36
|
-
if parsed_config.
|
46
|
+
if parsed_config.key? :auth
|
37
47
|
if parsed_config[:auth]['provider'] == 'dummy'
|
38
48
|
unless ENV['VMPOOLER_DEBUG']
|
39
49
|
warning = [
|
@@ -50,7 +60,7 @@ module Vmpooler
|
|
50
60
|
parsed_config[:config]['task_limit'] = string_to_int(ENV['TASK_LIMIT']) || parsed_config[:config]['task_limit'] || 10
|
51
61
|
parsed_config[:config]['migration_limit'] = string_to_int(ENV['MIGRATION_LIMIT']) if ENV['MIGRATION_LIMIT']
|
52
62
|
parsed_config[:config]['vm_checktime'] = string_to_int(ENV['VM_CHECKTIME']) || parsed_config[:config]['vm_checktime'] || 1
|
53
|
-
parsed_config[:config]['vm_lifetime'] = string_to_int(ENV['VM_LIFETIME']) || parsed_config[:config]['vm_lifetime']
|
63
|
+
parsed_config[:config]['vm_lifetime'] = string_to_int(ENV['VM_LIFETIME']) || parsed_config[:config]['vm_lifetime'] || 24
|
54
64
|
parsed_config[:config]['prefix'] = ENV['PREFIX'] || parsed_config[:config]['prefix'] || ''
|
55
65
|
|
56
66
|
parsed_config[:config]['logfile'] = ENV['LOGFILE'] if ENV['LOGFILE']
|
@@ -86,7 +96,7 @@ module Vmpooler
|
|
86
96
|
parsed_config[:graphite]['port'] = string_to_int(ENV['GRAPHITE_PORT']) if ENV['GRAPHITE_PORT']
|
87
97
|
|
88
98
|
parsed_config[:auth] = parsed_config[:auth] || {} if ENV['AUTH_PROVIDER']
|
89
|
-
if parsed_config.
|
99
|
+
if parsed_config.key? :auth
|
90
100
|
parsed_config[:auth]['provider'] = ENV['AUTH_PROVIDER'] if ENV['AUTH_PROVIDER']
|
91
101
|
parsed_config[:auth][:ldap] = parsed_config[:auth][:ldap] || {} if parsed_config[:auth]['provider'] == 'ldap'
|
92
102
|
parsed_config[:auth][:ldap]['host'] = ENV['LDAP_HOST'] if ENV['LDAP_HOST']
|
@@ -122,10 +132,8 @@ module Vmpooler
|
|
122
132
|
end
|
123
133
|
end
|
124
134
|
|
125
|
-
|
126
|
-
parsed_config[:tagfilter]
|
127
|
-
parsed_config[:tagfilter][tag] = Regexp.new(parsed_config[:tagfilter][tag])
|
128
|
-
end
|
135
|
+
parsed_config[:tagfilter]&.keys&.each do |tag|
|
136
|
+
parsed_config[:tagfilter][tag] = Regexp.new(parsed_config[:tagfilter][tag])
|
129
137
|
end
|
130
138
|
|
131
139
|
parsed_config[:uptime] = Time.now
|
@@ -171,7 +179,7 @@ module Vmpooler
|
|
171
179
|
def self.pool_index(pools)
|
172
180
|
pools_hash = {}
|
173
181
|
index = 0
|
174
|
-
|
182
|
+
pools.each do |pool|
|
175
183
|
pools_hash[pool['name']] = index
|
176
184
|
index += 1
|
177
185
|
end
|
@@ -182,14 +190,15 @@ module Vmpooler
|
|
182
190
|
# Returns a integer if input is a string
|
183
191
|
return if s.nil?
|
184
192
|
return unless s =~ /\d/
|
185
|
-
|
193
|
+
|
194
|
+
Integer(s)
|
186
195
|
end
|
187
196
|
|
188
197
|
def self.true?(obj)
|
189
|
-
obj.to_s.downcase ==
|
198
|
+
obj.to_s.downcase == 'true'
|
190
199
|
end
|
191
200
|
|
192
|
-
def self.set_linked_clone(parsed_config)
|
201
|
+
def self.set_linked_clone(parsed_config) # rubocop:disable Naming/AccessorMethodName
|
193
202
|
parsed_config[:config]['create_linked_clones'] = parsed_config[:config]['create_linked_clones'] || true
|
194
203
|
parsed_config[:config]['create_linked_clones'] = ENV['CREATE_LINKED_CLONES'] if ENV['CREATE_LINKED_CLONES'] =~ /true|false/
|
195
204
|
parsed_config[:config]['create_linked_clones'] = true?(parsed_config[:config]['create_linked_clones']) if parsed_config[:config]['create_linked_clones']
|
data/lib/vmpooler/api.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vmpooler
|
2
4
|
class API
|
3
5
|
class Dashboard < Sinatra::Base
|
4
|
-
|
5
6
|
helpers do
|
6
7
|
include Vmpooler::API::Helpers
|
7
8
|
end
|
@@ -21,9 +22,11 @@ module Vmpooler
|
|
21
22
|
|
22
23
|
if config[:graphs]
|
23
24
|
return false unless config[:graphs]['server']
|
25
|
+
|
24
26
|
@graph_server = config[:graphs]['server']
|
25
27
|
elsif config[:graphite]
|
26
28
|
return false unless config[:graphite]['server']
|
29
|
+
|
27
30
|
@graph_server = config[:graphite]['server']
|
28
31
|
else
|
29
32
|
false
|
@@ -36,9 +39,11 @@ module Vmpooler
|
|
36
39
|
|
37
40
|
if config[:graphs]
|
38
41
|
return 'vmpooler' unless config[:graphs]['prefix']
|
42
|
+
|
39
43
|
@graph_prefix = config[:graphs]['prefix']
|
40
44
|
elsif config[:graphite]
|
41
45
|
return false unless config[:graphite]['prefix']
|
46
|
+
|
42
47
|
@graph_prefix = config[:graphite]['prefix']
|
43
48
|
else
|
44
49
|
false
|
@@ -48,12 +53,14 @@ module Vmpooler
|
|
48
53
|
# what is the base URL for viewable graphs?
|
49
54
|
def graph_url
|
50
55
|
return false unless graph_server && graph_prefix
|
56
|
+
|
51
57
|
@graph_url ||= "http://#{graph_server}/render?target=#{graph_prefix}"
|
52
58
|
end
|
53
59
|
|
54
60
|
# return a full URL to a viewable graph for a given metrics target (graphite syntax)
|
55
61
|
def graph_link(target = '')
|
56
62
|
return '' unless graph_url
|
63
|
+
|
57
64
|
graph_url + target
|
58
65
|
end
|
59
66
|
|
@@ -76,7 +83,7 @@ module Vmpooler
|
|
76
83
|
history ||= {}
|
77
84
|
|
78
85
|
begin
|
79
|
-
buffer =
|
86
|
+
buffer = URI.parse(graph_link('.ready.*&from=-1hour&format=json')).read
|
80
87
|
history = JSON.parse(buffer)
|
81
88
|
|
82
89
|
history.each do |pool|
|
@@ -100,7 +107,7 @@ module Vmpooler
|
|
100
107
|
end
|
101
108
|
end
|
102
109
|
end
|
103
|
-
rescue
|
110
|
+
rescue StandardError
|
104
111
|
end
|
105
112
|
else
|
106
113
|
pools.each do |pool|
|
@@ -129,7 +136,7 @@ module Vmpooler
|
|
129
136
|
if params[:history]
|
130
137
|
if graph_url
|
131
138
|
begin
|
132
|
-
buffer =
|
139
|
+
buffer = URI.parse(graph_link('.running.*&from=-1hour&format=json')).read
|
133
140
|
JSON.parse(buffer).each do |pool|
|
134
141
|
if pool['target'] =~ /.*\.(.*)$/
|
135
142
|
pool['name'] = Regexp.last_match[1]
|
@@ -147,7 +154,7 @@ module Vmpooler
|
|
147
154
|
end
|
148
155
|
end
|
149
156
|
end
|
150
|
-
rescue
|
157
|
+
rescue StandardError
|
151
158
|
end
|
152
159
|
end
|
153
160
|
end
|
data/lib/vmpooler/api/helpers.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vmpooler
|
2
4
|
|
3
5
|
class API
|
@@ -71,43 +73,44 @@ module Vmpooler
|
|
71
73
|
)
|
72
74
|
|
73
75
|
return true if ldap.bind
|
76
|
+
|
74
77
|
return false
|
75
78
|
end
|
76
79
|
|
77
80
|
def authenticate(auth, username_str, password_str)
|
78
81
|
case auth['provider']
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
else
|
82
|
+
when 'dummy'
|
83
|
+
return (username_str != password_str)
|
84
|
+
when 'ldap'
|
85
|
+
ldap_base = auth[:ldap]['base']
|
86
|
+
ldap_port = auth[:ldap]['port'] || 389
|
87
|
+
ldap_user_obj = auth[:ldap]['user_object']
|
88
|
+
ldap_host = auth[:ldap]['host']
|
89
|
+
|
90
|
+
unless ldap_base.is_a? Array
|
91
|
+
ldap_base = ldap_base.split
|
92
|
+
end
|
93
|
+
|
94
|
+
unless ldap_user_obj.is_a? Array
|
95
|
+
ldap_user_obj = ldap_user_obj.split
|
96
|
+
end
|
97
|
+
|
98
|
+
ldap_base.each do |search_base|
|
99
|
+
ldap_user_obj.each do |search_user_obj|
|
98
100
|
result = authenticate_ldap(
|
99
101
|
ldap_port,
|
100
|
-
|
101
|
-
|
102
|
-
|
102
|
+
ldap_host,
|
103
|
+
search_user_obj,
|
104
|
+
search_base,
|
103
105
|
username_str,
|
104
|
-
password_str
|
106
|
+
password_str
|
105
107
|
)
|
106
|
-
return result
|
108
|
+
return true if result
|
107
109
|
end
|
108
|
-
|
109
|
-
return false
|
110
110
|
end
|
111
|
+
|
112
|
+
return false
|
113
|
+
end
|
111
114
|
end
|
112
115
|
|
113
116
|
def export_tags(backend, hostname, tags)
|
@@ -124,6 +127,7 @@ module Vmpooler
|
|
124
127
|
|
125
128
|
tags.each_pair do |tag, value|
|
126
129
|
next unless filter = Vmpooler::API.settings.config[:tagfilter][tag]
|
130
|
+
|
127
131
|
tags[tag] = value.match(filter).captures.join if value.match(filter)
|
128
132
|
end
|
129
133
|
|
@@ -161,7 +165,7 @@ module Vmpooler
|
|
161
165
|
backend.scard(key + pool['name'])
|
162
166
|
end
|
163
167
|
end
|
164
|
-
res.inject(0){ |m, x| m+x }.to_i
|
168
|
+
res.inject(0) { |m, x| m + x }.to_i
|
165
169
|
end
|
166
170
|
|
167
171
|
# Takes the pools and a key to run scard on
|
@@ -201,18 +205,18 @@ module Vmpooler
|
|
201
205
|
def get_capacity_metrics(pools, backend)
|
202
206
|
capacity = {
|
203
207
|
current: 0,
|
204
|
-
total:
|
208
|
+
total: 0,
|
205
209
|
percent: 0
|
206
210
|
}
|
207
211
|
|
208
212
|
pools.each do |pool|
|
209
|
-
capacity[:total]
|
213
|
+
capacity[:total] += pool['size'].to_i
|
210
214
|
end
|
211
215
|
|
212
216
|
capacity[:current] = get_total_across_pools_redis_scard(pools, 'vmpooler__ready__', backend)
|
213
217
|
|
214
218
|
if capacity[:total] > 0
|
215
|
-
capacity[:percent] = (
|
219
|
+
capacity[:percent] = (capacity[:current].fdiv(capacity[:total]) * 100.0).round(1)
|
216
220
|
end
|
217
221
|
|
218
222
|
capacity
|
@@ -220,16 +224,16 @@ module Vmpooler
|
|
220
224
|
|
221
225
|
def get_queue_metrics(pools, backend)
|
222
226
|
queue = {
|
223
|
-
pending:
|
224
|
-
cloning:
|
225
|
-
booting:
|
226
|
-
ready:
|
227
|
-
running:
|
227
|
+
pending: 0,
|
228
|
+
cloning: 0,
|
229
|
+
booting: 0,
|
230
|
+
ready: 0,
|
231
|
+
running: 0,
|
228
232
|
completed: 0,
|
229
|
-
total:
|
233
|
+
total: 0
|
230
234
|
}
|
231
235
|
|
232
|
-
queue[:pending] = get_total_across_pools_redis_scard(pools,'vmpooler__pending__', backend)
|
236
|
+
queue[:pending] = get_total_across_pools_redis_scard(pools, 'vmpooler__pending__', backend)
|
233
237
|
queue[:ready] = get_total_across_pools_redis_scard(pools, 'vmpooler__ready__', backend)
|
234
238
|
queue[:running] = get_total_across_pools_redis_scard(pools, 'vmpooler__running__', backend)
|
235
239
|
queue[:completed] = get_total_across_pools_redis_scard(pools, 'vmpooler__completed__', backend)
|
@@ -306,11 +310,11 @@ module Vmpooler
|
|
306
310
|
task = {
|
307
311
|
duration: {
|
308
312
|
average: 0,
|
309
|
-
min:
|
310
|
-
max:
|
311
|
-
total:
|
313
|
+
min: 0,
|
314
|
+
max: 0,
|
315
|
+
total: 0
|
312
316
|
},
|
313
|
-
count:
|
317
|
+
count: {
|
314
318
|
total: 0
|
315
319
|
}
|
316
320
|
}
|
@@ -450,7 +454,7 @@ module Vmpooler
|
|
450
454
|
def pool_index(pools)
|
451
455
|
pools_hash = {}
|
452
456
|
index = 0
|
453
|
-
|
457
|
+
pools.each do |pool|
|
454
458
|
pools_hash[pool['name']] = index
|
455
459
|
index += 1
|
456
460
|
end
|
@@ -461,13 +465,14 @@ module Vmpooler
|
|
461
465
|
prepared_template = backend.hget('vmpooler__template__prepared', pool['name'])
|
462
466
|
return false if prepared_template.nil?
|
463
467
|
return true if pool['template'] == prepared_template
|
468
|
+
|
464
469
|
return false
|
465
470
|
end
|
466
471
|
|
467
472
|
def is_integer?(x)
|
468
473
|
Integer(x)
|
469
474
|
true
|
470
|
-
rescue
|
475
|
+
rescue StandardError
|
471
476
|
false
|
472
477
|
end
|
473
478
|
|
@@ -487,7 +492,7 @@ module Vmpooler
|
|
487
492
|
def vm_ready?(vm_name, domain = nil)
|
488
493
|
begin
|
489
494
|
open_socket(vm_name, domain)
|
490
|
-
rescue =>
|
495
|
+
rescue StandardError => _e
|
491
496
|
return false
|
492
497
|
end
|
493
498
|
|
data/lib/vmpooler/api/reroute.rb
CHANGED
data/lib/vmpooler/api/v1.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Vmpooler
|
2
4
|
class API
|
3
5
|
class V1 < Sinatra::Base
|
@@ -37,22 +39,24 @@ module Vmpooler
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def checkoutlock
|
40
|
-
Vmpooler::API
|
42
|
+
Vmpooler::API.settings.checkoutlock
|
41
43
|
end
|
42
44
|
|
43
45
|
def fetch_single_vm(template)
|
44
46
|
template_backends = [template]
|
45
47
|
aliases = Vmpooler::API.settings.config[:alias]
|
46
48
|
if aliases
|
47
|
-
template_backends
|
49
|
+
template_backends += aliases[template] if aliases[template].is_a?(Array)
|
48
50
|
template_backends << aliases[template] if aliases[template].is_a?(String)
|
49
51
|
pool_index = pool_index(pools)
|
50
52
|
weighted_pools = {}
|
51
53
|
template_backends.each do |t|
|
52
54
|
next unless pool_index.key? t
|
55
|
+
|
53
56
|
index = pool_index[t]
|
54
57
|
clone_target = pools[index]['clone_target'] || config['clone_target']
|
55
58
|
next unless config.key?('backend_weight')
|
59
|
+
|
56
60
|
weight = config['backend_weight'][clone_target]
|
57
61
|
if weight
|
58
62
|
weighted_pools[t] = weight
|
@@ -75,11 +79,17 @@ module Vmpooler
|
|
75
79
|
template_backends.each do |template_backend|
|
76
80
|
vms = backend.smembers("vmpooler__ready__#{template_backend}")
|
77
81
|
next if vms.empty?
|
82
|
+
|
78
83
|
vms.reverse.each do |vm|
|
79
84
|
ready = vm_ready?(vm, config['domain'])
|
80
85
|
if ready
|
81
|
-
backend.smove("vmpooler__ready__#{template_backend}", "vmpooler__running__#{template_backend}", vm)
|
82
|
-
|
86
|
+
smoved = backend.smove("vmpooler__ready__#{template_backend}", "vmpooler__running__#{template_backend}", vm)
|
87
|
+
if smoved
|
88
|
+
return [vm, template_backend, template]
|
89
|
+
else
|
90
|
+
metrics.increment("checkout.smove.failed.#{template_backend}")
|
91
|
+
return [nil, nil, nil]
|
92
|
+
end
|
83
93
|
else
|
84
94
|
backend.smove("vmpooler__ready__#{template_backend}", "vmpooler__completed__#{template_backend}", vm)
|
85
95
|
metrics.increment("checkout.nonresponsive.#{template_backend}")
|
@@ -104,7 +114,7 @@ module Vmpooler
|
|
104
114
|
|
105
115
|
backend.hset('vmpooler__vm__' + vm, 'token:token', request.env['HTTP_X_AUTH_TOKEN'])
|
106
116
|
backend.hset('vmpooler__vm__' + vm, 'token:user',
|
107
|
-
|
117
|
+
backend.hget('vmpooler__token__' + request.env['HTTP_X_AUTH_TOKEN'], 'user')
|
108
118
|
)
|
109
119
|
|
110
120
|
if config['vm_lifetime_auth'].to_i > 0
|
@@ -136,14 +146,14 @@ module Vmpooler
|
|
136
146
|
metrics.increment('checkout.empty.' + requested)
|
137
147
|
break
|
138
148
|
else
|
139
|
-
vms << [
|
149
|
+
vms << [vmpool, vmname, vmtemplate]
|
140
150
|
metrics.increment('checkout.success.' + vmtemplate)
|
141
151
|
end
|
142
152
|
end
|
143
153
|
end
|
144
154
|
|
145
155
|
if failed
|
146
|
-
vms.each do |(vmpool, vmname,
|
156
|
+
vms.each do |(vmpool, vmname, _vmtemplate)|
|
147
157
|
return_vm_to_ready_state(vmpool, vmname)
|
148
158
|
end
|
149
159
|
status 503
|
@@ -203,7 +213,7 @@ module Vmpooler
|
|
203
213
|
def reset_pool(payload)
|
204
214
|
result = { 'ok' => false }
|
205
215
|
|
206
|
-
payload.each do |poolname,
|
216
|
+
payload.each do |poolname, _count|
|
207
217
|
backend.sadd('vmpooler__poolreset', poolname)
|
208
218
|
end
|
209
219
|
status 201
|
@@ -220,7 +230,7 @@ module Vmpooler
|
|
220
230
|
|
221
231
|
payload.each do |poolname, clone_target|
|
222
232
|
unless pools[pool_index[poolname]]['clone_target'] == clone_target
|
223
|
-
pools[pool_index[poolname]]['clone_target']
|
233
|
+
pools[pool_index[poolname]]['clone_target'] = clone_target
|
224
234
|
backend.hset('vmpooler__config__clone_target', poolname, clone_target)
|
225
235
|
pools_updated += 1
|
226
236
|
status 201
|
@@ -234,42 +244,36 @@ module Vmpooler
|
|
234
244
|
def sync_pool_templates
|
235
245
|
pool_index = pool_index(pools)
|
236
246
|
template_configs = backend.hgetall('vmpooler__config__template')
|
237
|
-
|
238
|
-
template_configs.each do |poolname, template|
|
247
|
+
template_configs&.each do |poolname, template|
|
239
248
|
if pool_index.include? poolname
|
240
249
|
unless pools[pool_index[poolname]]['template'] == template
|
241
250
|
pools[pool_index[poolname]]['template'] = template
|
242
251
|
end
|
243
252
|
end
|
244
|
-
end
|
245
253
|
end
|
246
254
|
end
|
247
255
|
|
248
256
|
def sync_pool_sizes
|
249
257
|
pool_index = pool_index(pools)
|
250
258
|
poolsize_configs = backend.hgetall('vmpooler__config__poolsize')
|
251
|
-
|
252
|
-
poolsize_configs.each do |poolname, size|
|
259
|
+
poolsize_configs&.each do |poolname, size|
|
253
260
|
if pool_index.include? poolname
|
254
261
|
unless pools[pool_index[poolname]]['size'] == size.to_i
|
255
262
|
pools[pool_index[poolname]]['size'] == size.to_i
|
256
263
|
end
|
257
264
|
end
|
258
|
-
end
|
259
265
|
end
|
260
266
|
end
|
261
267
|
|
262
268
|
def sync_clone_targets
|
263
269
|
pool_index = pool_index(pools)
|
264
270
|
clone_target_configs = backend.hgetall('vmpooler__config__clone_target')
|
265
|
-
|
266
|
-
clone_target_configs.each do |poolname, clone_target|
|
271
|
+
clone_target_configs&.each do |poolname, clone_target|
|
267
272
|
if pool_index.include? poolname
|
268
273
|
unless pools[pool_index[poolname]]['clone_target'] == clone_target
|
269
274
|
pools[pool_index[poolname]]['clone_target'] == clone_target
|
270
|
-
|
275
|
+
end
|
271
276
|
end
|
272
|
-
end
|
273
277
|
end
|
274
278
|
end
|
275
279
|
|
@@ -368,36 +372,38 @@ module Vmpooler
|
|
368
372
|
pending_hash = get_list_across_pools_redis_scard(pools, 'vmpooler__pending__', backend)
|
369
373
|
lastBoot_hash = get_list_across_pools_redis_hget(pools, 'vmpooler__lastboot', backend)
|
370
374
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
375
|
+
unless views and not views.include?("pools")
|
376
|
+
pools.each do |pool|
|
377
|
+
# REMIND: move this out of the API and into the back-end
|
378
|
+
ready = ready_hash[pool['name']]
|
379
|
+
running = running_hash[pool['name']]
|
380
|
+
pending = pending_hash[pool['name']]
|
381
|
+
max = pool['size']
|
382
|
+
lastBoot = lastBoot_hash[pool['name']]
|
383
|
+
aka = pool['alias']
|
384
|
+
|
385
|
+
result[:pools][pool['name']] = {
|
386
|
+
ready: ready,
|
387
|
+
running: running,
|
388
|
+
pending: pending,
|
389
|
+
max: max,
|
390
|
+
lastBoot: lastBoot
|
391
|
+
}
|
387
392
|
|
388
|
-
|
389
|
-
|
390
|
-
|
393
|
+
if aka
|
394
|
+
result[:pools][pool['name']][:alias] = aka
|
395
|
+
end
|
391
396
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
397
|
+
# for backwards compatibility, include separate "empty" stats in "status" block
|
398
|
+
if ready == 0
|
399
|
+
result[:status][:empty] ||= []
|
400
|
+
result[:status][:empty].push(pool['name'])
|
396
401
|
|
397
|
-
|
398
|
-
|
402
|
+
result[:status][:ok] = false
|
403
|
+
result[:status][:message] = "Found #{result[:status][:empty].length} empty pools."
|
404
|
+
end
|
399
405
|
end
|
400
|
-
end
|
406
|
+
end
|
401
407
|
|
402
408
|
result[:status][:uptime] = (Time.now - Vmpooler::API.settings.config[:uptime]).round(1) if Vmpooler::API.settings.config[:uptime]
|
403
409
|
|
@@ -442,7 +448,6 @@ module Vmpooler
|
|
442
448
|
if aka
|
443
449
|
result[:pools][pool['name']][:alias] = aka
|
444
450
|
end
|
445
|
-
|
446
451
|
end
|
447
452
|
|
448
453
|
ready_hash = get_list_across_pools_redis_scard(poolscopy, 'vmpooler__ready__', backend)
|
@@ -456,7 +461,7 @@ module Vmpooler
|
|
456
461
|
get "#{api_prefix}/totalrunning/?" do
|
457
462
|
content_type :json
|
458
463
|
queue = {
|
459
|
-
running:
|
464
|
+
running: 0
|
460
465
|
}
|
461
466
|
|
462
467
|
queue[:running] = get_total_across_pools_redis_scard(pools, 'vmpooler__running__', backend)
|
@@ -753,7 +758,7 @@ module Vmpooler
|
|
753
758
|
|
754
759
|
def invalid_pool(payload)
|
755
760
|
invalid = []
|
756
|
-
payload.each do |pool,
|
761
|
+
payload.each do |pool, _clone_target|
|
757
762
|
invalid << pool unless pool_exists?(pool)
|
758
763
|
end
|
759
764
|
invalid
|
@@ -837,7 +842,7 @@ module Vmpooler
|
|
837
842
|
# Look up IP address of the hostname
|
838
843
|
begin
|
839
844
|
ipAddress = TCPSocket.gethostbyname(params[:hostname])[3]
|
840
|
-
rescue
|
845
|
+
rescue StandardError
|
841
846
|
ipAddress = ""
|
842
847
|
end
|
843
848
|
|
@@ -874,6 +879,8 @@ module Vmpooler
|
|
874
879
|
|
875
880
|
status 200
|
876
881
|
result['ok'] = true
|
882
|
+
else
|
883
|
+
metrics.increment('delete.srem.failed')
|
877
884
|
end
|
878
885
|
end
|
879
886
|
|
@@ -893,7 +900,7 @@ module Vmpooler
|
|
893
900
|
if backend.exists('vmpooler__vm__' + params[:hostname])
|
894
901
|
begin
|
895
902
|
jdata = JSON.parse(request.body.read)
|
896
|
-
rescue
|
903
|
+
rescue StandardError
|
897
904
|
halt 400, JSON.pretty_generate(result)
|
898
905
|
end
|
899
906
|
|
@@ -909,13 +916,6 @@ module Vmpooler
|
|
909
916
|
max_lifetime_upper_limit = max_lifetime_upper_limit.to_i
|
910
917
|
if arg.to_i >= max_lifetime_upper_limit
|
911
918
|
failure.push("You provided a lifetime (#{arg}) that exceeds the configured maximum of #{max_lifetime_upper_limit}.")
|
912
|
-
else
|
913
|
-
# also make sure we do not extend past max_lifetime_upper_limit
|
914
|
-
rdata = backend.hgetall('vmpooler__vm__' + params[:hostname])
|
915
|
-
running = ((Time.now - Time.parse(rdata['checkout'])) / 60 / 60).round(2)
|
916
|
-
unless running + arg.to_i < max_lifetime_upper_limit
|
917
|
-
failure.push("You provided a lifetime (#{arg}) that will extend the current lifetime past the configured maximum of #{max_lifetime_upper_limit}.")
|
918
|
-
end
|
919
919
|
end
|
920
920
|
end
|
921
921
|
|
@@ -936,7 +936,7 @@ module Vmpooler
|
|
936
936
|
end
|
937
937
|
end
|
938
938
|
|
939
|
-
if failure.
|
939
|
+
if !failure.empty?
|
940
940
|
status 400
|
941
941
|
result['failure'] = failure
|
942
942
|
else
|