vmpooler 0.14.1 → 0.14.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a97df538d5070e9eb9854084473c50efdd3b18427dc6909e6bfadaeea0f329e
4
- data.tar.gz: 930c7c450fcee1429d18a8b72a48cd9c199d659bdb430a5ef5933eb6911cc1ca
3
+ metadata.gz: 1dcbff566ca53b6dd3ec05d98b1210b83552e7389a9a9943a20f81984839b8ac
4
+ data.tar.gz: 9a3bdcd8323fcc806c532e610f8a0a28246c84ad98c46744a48c069222169faa
5
5
  SHA512:
6
- metadata.gz: a9706740f3aca1a51fecc17550a1d75275849148c658622ca05f9f177dd1bfd8e84ba681701c9074215057e65854026395e765d5b346305772f572a4f6bf6a9e
7
- data.tar.gz: e1e8f8687342676d40d75c5771b62a28b8f865208882d8ae0d7f0548f218cc6134cce5e53190c46197d56892eda687e1798a5e7c91f35b27510fa84bd9eb1f68
6
+ metadata.gz: 00adf48793ad92e95bd9400cecd2993b18c60617c5a272d402009e905654e85b9ec2cef361dbb80f0bfc7978180299bb6b06392c87df48739a66a03c2c26639d
7
+ data.tar.gz: 5f1970fe7d1a74e8430908531cf0e9d67845054250b9d681fdbe43752d393779f1976160f4d479628441aeaf60085acb3cfaafd52476301eb255f52de586c98b
@@ -9,6 +9,7 @@ redis_port = config[:redis]['port']
9
9
  redis_password = config[:redis]['password']
10
10
  redis_connection_pool_size = config[:redis]['connection_pool_size']
11
11
  redis_connection_pool_timeout = config[:redis]['connection_pool_timeout']
12
+ redis_reconnect_attempts = config[:redis]['reconnect_attempts']
12
13
  logger_file = config[:config]['logfile']
13
14
 
14
15
  logger = Vmpooler::Logger.new logger_file
@@ -43,7 +44,7 @@ if torun.include? :manager
43
44
  Vmpooler::PoolManager.new(
44
45
  config,
45
46
  logger,
46
- Vmpooler.redis_connection_pool(redis_host, redis_port, redis_password, redis_connection_pool_size, redis_connection_pool_timeout, metrics),
47
+ Vmpooler.redis_connection_pool(redis_host, redis_port, redis_password, redis_connection_pool_size, redis_connection_pool_timeout, metrics, redis_reconnect_attempts),
47
48
  metrics
48
49
  ).execute!
49
50
  end
@@ -58,59 +58,58 @@ module Vmpooler
58
58
  end
59
59
 
60
60
  # Set some configuration defaults
61
- parsed_config[:config]['task_limit'] = string_to_int(ENV['TASK_LIMIT']) || parsed_config[:config]['task_limit'] || 10
62
- parsed_config[:config]['ondemand_clone_limit'] = string_to_int(ENV['ONDEMAND_CLONE_LIMIT']) || parsed_config[:config]['ondemand_clone_limit'] || 10
61
+ parsed_config[:config]['task_limit'] = string_to_int(ENV['TASK_LIMIT']) || parsed_config[:config]['task_limit'] || 10
62
+ parsed_config[:config]['ondemand_clone_limit'] = string_to_int(ENV['ONDEMAND_CLONE_LIMIT']) || parsed_config[:config]['ondemand_clone_limit'] || 10
63
63
  parsed_config[:config]['max_ondemand_instances_per_request'] = string_to_int(ENV['MAX_ONDEMAND_INSTANCES_PER_REQUEST']) || parsed_config[:config]['max_ondemand_instances_per_request'] || 10
64
- parsed_config[:config]['migration_limit'] = string_to_int(ENV['MIGRATION_LIMIT']) if ENV['MIGRATION_LIMIT']
65
- parsed_config[:config]['vm_checktime'] = string_to_int(ENV['VM_CHECKTIME']) || parsed_config[:config]['vm_checktime'] || 1
66
- parsed_config[:config]['vm_lifetime'] = string_to_int(ENV['VM_LIFETIME']) || parsed_config[:config]['vm_lifetime'] || 24
67
- parsed_config[:config]['max_lifetime_upper_limit'] = string_to_int(ENV['MAX_LIFETIME_UPPER_LIMIT']) || parsed_config[:config]['max_lifetime_upper_limit']
68
- parsed_config[:config]['ready_ttl'] = string_to_int(ENV['READY_TTL']) || parsed_config[:config]['ready_ttl'] || 60
69
- parsed_config[:config]['ondemand_request_ttl'] = string_to_int(ENV['ONDEMAND_REQUEST_TTL']) || parsed_config[:config]['ondemand_request_ttl'] || 5
70
- parsed_config[:config]['prefix'] = ENV['PREFIX'] || parsed_config[:config]['prefix'] || ''
71
-
72
- parsed_config[:config]['logfile'] = ENV['LOGFILE'] if ENV['LOGFILE']
73
-
74
- parsed_config[:config]['site_name'] = ENV['SITE_NAME'] if ENV['SITE_NAME']
75
- parsed_config[:config]['domain'] = ENV['DOMAIN'] if ENV['DOMAIN']
76
- parsed_config[:config]['clone_target'] = ENV['CLONE_TARGET'] if ENV['CLONE_TARGET']
77
- parsed_config[:config]['timeout'] = string_to_int(ENV['TIMEOUT']) if ENV['TIMEOUT']
78
- parsed_config[:config]['vm_lifetime_auth'] = string_to_int(ENV['VM_LIFETIME_AUTH']) if ENV['VM_LIFETIME_AUTH']
79
- parsed_config[:config]['max_tries'] = string_to_int(ENV['MAX_TRIES']) if ENV['MAX_TRIES']
80
- parsed_config[:config]['retry_factor'] = string_to_int(ENV['RETRY_FACTOR']) if ENV['RETRY_FACTOR']
81
- parsed_config[:config]['create_folders'] = true?(ENV['CREATE_FOLDERS']) if ENV['CREATE_FOLDERS']
82
- parsed_config[:config]['create_template_delta_disks'] = ENV['CREATE_TEMPLATE_DELTA_DISKS'] if ENV['CREATE_TEMPLATE_DELTA_DISKS']
64
+ parsed_config[:config]['migration_limit'] = string_to_int(ENV['MIGRATION_LIMIT']) if ENV['MIGRATION_LIMIT']
65
+ parsed_config[:config]['vm_checktime'] = string_to_int(ENV['VM_CHECKTIME']) || parsed_config[:config]['vm_checktime'] || 1
66
+ parsed_config[:config]['vm_lifetime'] = string_to_int(ENV['VM_LIFETIME']) || parsed_config[:config]['vm_lifetime'] || 24
67
+ parsed_config[:config]['max_lifetime_upper_limit'] = string_to_int(ENV['MAX_LIFETIME_UPPER_LIMIT']) || parsed_config[:config]['max_lifetime_upper_limit']
68
+ parsed_config[:config]['ready_ttl'] = string_to_int(ENV['READY_TTL']) || parsed_config[:config]['ready_ttl'] || 60
69
+ parsed_config[:config]['ondemand_request_ttl'] = string_to_int(ENV['ONDEMAND_REQUEST_TTL']) || parsed_config[:config]['ondemand_request_ttl'] || 5
70
+ parsed_config[:config]['prefix'] = ENV['PREFIX'] || parsed_config[:config]['prefix'] || ''
71
+ parsed_config[:config]['logfile'] = ENV['LOGFILE'] if ENV['LOGFILE']
72
+ parsed_config[:config]['site_name'] = ENV['SITE_NAME'] if ENV['SITE_NAME']
73
+ parsed_config[:config]['domain'] = ENV['DOMAIN'] if ENV['DOMAIN']
74
+ parsed_config[:config]['clone_target'] = ENV['CLONE_TARGET'] if ENV['CLONE_TARGET']
75
+ parsed_config[:config]['timeout'] = string_to_int(ENV['TIMEOUT']) if ENV['TIMEOUT']
76
+ parsed_config[:config]['vm_lifetime_auth'] = string_to_int(ENV['VM_LIFETIME_AUTH']) if ENV['VM_LIFETIME_AUTH']
77
+ parsed_config[:config]['max_tries'] = string_to_int(ENV['MAX_TRIES']) if ENV['MAX_TRIES']
78
+ parsed_config[:config]['retry_factor'] = string_to_int(ENV['RETRY_FACTOR']) if ENV['RETRY_FACTOR']
79
+ parsed_config[:config]['create_folders'] = true?(ENV['CREATE_FOLDERS']) if ENV['CREATE_FOLDERS']
80
+ parsed_config[:config]['experimental_features'] = ENV['EXPERIMENTAL_FEATURES'] if ENV['EXPERIMENTAL_FEATURES']
81
+ parsed_config[:config]['purge_unconfigured_folders'] = ENV['PURGE_UNCONFIGURED_FOLDERS'] if ENV['PURGE_UNCONFIGURED_FOLDERS']
82
+ parsed_config[:config]['usage_stats'] = ENV['USAGE_STATS'] if ENV['USAGE_STATS']
83
+ parsed_config[:config]['request_logger'] = ENV['REQUEST_LOGGER'] if ENV['REQUEST_LOGGER']
84
+ parsed_config[:config]['create_template_delta_disks'] = ENV['CREATE_TEMPLATE_DELTA_DISKS'] if ENV['CREATE_TEMPLATE_DELTA_DISKS']
83
85
  set_linked_clone(parsed_config)
84
- parsed_config[:config]['experimental_features'] = ENV['EXPERIMENTAL_FEATURES'] if ENV['EXPERIMENTAL_FEATURES']
85
- parsed_config[:config]['purge_unconfigured_folders'] = ENV['PURGE_UNCONFIGURED_FOLDERS'] if ENV['PURGE_UNCONFIGURED_FOLDERS']
86
- parsed_config[:config]['usage_stats'] = ENV['USAGE_STATS'] if ENV['USAGE_STATS']
87
- parsed_config[:config]['request_logger'] = ENV['REQUEST_LOGGER'] if ENV['REQUEST_LOGGER']
88
-
89
- parsed_config[:redis] = parsed_config[:redis] || {}
90
- parsed_config[:redis]['server'] = ENV['REDIS_SERVER'] || parsed_config[:redis]['server'] || 'localhost'
91
- parsed_config[:redis]['port'] = string_to_int(ENV['REDIS_PORT']) if ENV['REDIS_PORT']
92
- parsed_config[:redis]['password'] = ENV['REDIS_PASSWORD'] if ENV['REDIS_PASSWORD']
93
- parsed_config[:redis]['data_ttl'] = string_to_int(ENV['REDIS_DATA_TTL']) || parsed_config[:redis]['data_ttl'] || 168
94
- parsed_config[:redis]['connection_pool_size'] = string_to_int(ENV['REDIS_CONNECTION_POOL_SIZE']) || parsed_config[:redis]['connection_pool_size'] || 10
86
+
87
+ parsed_config[:redis] = parsed_config[:redis] || {}
88
+ parsed_config[:redis]['server'] = ENV['REDIS_SERVER'] || parsed_config[:redis]['server'] || 'localhost'
89
+ parsed_config[:redis]['port'] = string_to_int(ENV['REDIS_PORT']) if ENV['REDIS_PORT']
90
+ parsed_config[:redis]['password'] = ENV['REDIS_PASSWORD'] if ENV['REDIS_PASSWORD']
91
+ parsed_config[:redis]['data_ttl'] = string_to_int(ENV['REDIS_DATA_TTL']) || parsed_config[:redis]['data_ttl'] || 168
92
+ parsed_config[:redis]['connection_pool_size'] = string_to_int(ENV['REDIS_CONNECTION_POOL_SIZE']) || parsed_config[:redis]['connection_pool_size'] || 10
95
93
  parsed_config[:redis]['connection_pool_timeout'] = string_to_int(ENV['REDIS_CONNECTION_POOL_TIMEOUT']) || parsed_config[:redis]['connection_pool_timeout'] || 5
94
+ parsed_config[:redis]['reconnect_attempts'] = string_to_int(ENV['REDIS_RECONNECT_ATTEMPTS']) || parsed_config[:redis]['reconnect_attempts'] || 10
96
95
 
97
- parsed_config[:statsd] = parsed_config[:statsd] || {} if ENV['STATSD_SERVER']
96
+ parsed_config[:statsd] = parsed_config[:statsd] || {} if ENV['STATSD_SERVER']
98
97
  parsed_config[:statsd]['server'] = ENV['STATSD_SERVER'] if ENV['STATSD_SERVER']
99
98
  parsed_config[:statsd]['prefix'] = ENV['STATSD_PREFIX'] if ENV['STATSD_PREFIX']
100
- parsed_config[:statsd]['port'] = string_to_int(ENV['STATSD_PORT']) if ENV['STATSD_PORT']
99
+ parsed_config[:statsd]['port'] = string_to_int(ENV['STATSD_PORT']) if ENV['STATSD_PORT']
101
100
 
102
- parsed_config[:graphite] = parsed_config[:graphite] || {} if ENV['GRAPHITE_SERVER']
101
+ parsed_config[:graphite] = parsed_config[:graphite] || {} if ENV['GRAPHITE_SERVER']
103
102
  parsed_config[:graphite]['server'] = ENV['GRAPHITE_SERVER'] if ENV['GRAPHITE_SERVER']
104
103
  parsed_config[:graphite]['prefix'] = ENV['GRAPHITE_PREFIX'] if ENV['GRAPHITE_PREFIX']
105
- parsed_config[:graphite]['port'] = string_to_int(ENV['GRAPHITE_PORT']) if ENV['GRAPHITE_PORT']
104
+ parsed_config[:graphite]['port'] = string_to_int(ENV['GRAPHITE_PORT']) if ENV['GRAPHITE_PORT']
106
105
 
107
106
  parsed_config[:auth] = parsed_config[:auth] || {} if ENV['AUTH_PROVIDER']
108
107
  if parsed_config.key? :auth
109
- parsed_config[:auth]['provider'] = ENV['AUTH_PROVIDER'] if ENV['AUTH_PROVIDER']
110
- parsed_config[:auth][:ldap] = parsed_config[:auth][:ldap] || {} if parsed_config[:auth]['provider'] == 'ldap'
111
- parsed_config[:auth][:ldap]['host'] = ENV['LDAP_HOST'] if ENV['LDAP_HOST']
112
- parsed_config[:auth][:ldap]['port'] = string_to_int(ENV['LDAP_PORT']) if ENV['LDAP_PORT']
113
- parsed_config[:auth][:ldap]['base'] = ENV['LDAP_BASE'] if ENV['LDAP_BASE']
108
+ parsed_config[:auth]['provider'] = ENV['AUTH_PROVIDER'] if ENV['AUTH_PROVIDER']
109
+ parsed_config[:auth][:ldap] = parsed_config[:auth][:ldap] || {} if parsed_config[:auth]['provider'] == 'ldap'
110
+ parsed_config[:auth][:ldap]['host'] = ENV['LDAP_HOST'] if ENV['LDAP_HOST']
111
+ parsed_config[:auth][:ldap]['port'] = string_to_int(ENV['LDAP_PORT']) if ENV['LDAP_PORT']
112
+ parsed_config[:auth][:ldap]['base'] = ENV['LDAP_BASE'] if ENV['LDAP_BASE']
114
113
  parsed_config[:auth][:ldap]['user_object'] = ENV['LDAP_USER_OBJECT'] if ENV['LDAP_USER_OBJECT']
115
114
  end
116
115
 
@@ -164,7 +163,7 @@ module Vmpooler
164
163
  pools
165
164
  end
166
165
 
167
- def self.redis_connection_pool(host, port, password, size, timeout, metrics)
166
+ def self.redis_connection_pool(host, port, password, size, timeout, metrics, redis_reconnect_attempts = 0)
168
167
  Vmpooler::PoolManager::GenericConnectionPool.new(
169
168
  metrics: metrics,
170
169
  connpool_type: 'redis_connection_pool',
@@ -173,13 +172,14 @@ module Vmpooler
173
172
  timeout: timeout
174
173
  ) do
175
174
  connection = Concurrent::Hash.new
176
- redis = new_redis(host, port, password)
175
+ redis = new_redis(host, port, password, redis_reconnect_attempts)
177
176
  connection['connection'] = redis
178
177
  end
179
178
  end
180
179
 
181
- def self.new_redis(host = 'localhost', port = nil, password = nil)
182
- Redis.new(host: host, port: port, password: password)
180
+ def self.new_redis(host = 'localhost', port = nil, password = nil, redis_reconnect_attempts = 10)
181
+ Redis.new(host: host, port: port, password: password, reconnect_attempts: redis_reconnect_attempts, reconnect_delay: 1.5,
182
+ reconnect_delay_max: 10.0)
183
183
  end
184
184
 
185
185
  def self.pools(conf)
@@ -38,8 +38,8 @@ module Vmpooler
38
38
  # Using customised collector that filters out hostnames on API paths
39
39
  require 'vmpooler/metrics/promstats/collector_middleware'
40
40
  require 'prometheus/middleware/exporter'
41
- use Vmpooler::Metrics::Promstats::CollectorMiddleware, metrics_prefix: "#{metrics.metrics_prefix}_http"
42
- use Prometheus::Middleware::Exporter, path: metrics.endpoint
41
+ use Vmpooler::Metrics::Promstats::CollectorMiddleware, metrics_prefix: "#{metrics.prometheus_prefix}_http"
42
+ use Prometheus::Middleware::Exporter, path: metrics.prometheus_endpoint
43
43
  end
44
44
 
45
45
  if torun.include? :api
@@ -89,18 +89,16 @@ module Vmpooler
89
89
  template_backends += aliases
90
90
  weighted_pools = get_pool_weights(template_backends)
91
91
 
92
- pickup = Pickup.new(weighted_pools) if weighted_pools.count == template_backends.count
93
- count.to_i.times do
94
- if pickup
92
+ if weighted_pools.count > 1 && weighted_pools.count == template_backends.count
93
+ pickup = Pickup.new(weighted_pools)
94
+ count.to_i.times do
95
95
  selection << pickup.pick
96
- else
96
+ end
97
+ else
98
+ count.to_i.times do
97
99
  selection << template_backends.sample
98
100
  end
99
101
  end
100
- else
101
- count.to_i.times do
102
- selection << template
103
- end
104
102
  end
105
103
 
106
104
  count_selection(selection)
@@ -809,7 +807,7 @@ module Vmpooler
809
807
 
810
808
  post "#{api_prefix}/ondemandvm/?" do
811
809
  content_type :json
812
- metrics.increment('api_vm.post.ondemand.requestid')
810
+ metrics.increment('http_requests_vm_total.post.ondemand.requestid')
813
811
 
814
812
  need_token! if Vmpooler::API.settings.config[:auth]
815
813
 
@@ -847,7 +845,7 @@ module Vmpooler
847
845
  post "#{api_prefix}/ondemandvm/:template/?" do
848
846
  content_type :json
849
847
  result = { 'ok' => false }
850
- metrics.increment('api_vm.delete.ondemand.template')
848
+ metrics.increment('http_requests_vm_total.delete.ondemand.template')
851
849
 
852
850
  need_token! if Vmpooler::API.settings.config[:auth]
853
851
 
@@ -874,7 +872,7 @@ module Vmpooler
874
872
 
875
873
  get "#{api_prefix}/ondemandvm/:requestid/?" do
876
874
  content_type :json
877
- metrics.increment('api_vm.get.ondemand.request')
875
+ metrics.increment('http_requests_vm_total.get.ondemand.request')
878
876
 
879
877
  status 404
880
878
  result = check_ondemand_request(params[:requestid])
@@ -885,7 +883,7 @@ module Vmpooler
885
883
  delete "#{api_prefix}/ondemandvm/:requestid/?" do
886
884
  content_type :json
887
885
  need_token! if Vmpooler::API.settings.config[:auth]
888
- metrics.increment('api_vm.delete.ondemand.request')
886
+ metrics.increment('http_requests_vm_total.delete.ondemand.request')
889
887
 
890
888
  status 404
891
889
  result = delete_ondemand_request(params[:requestid])
@@ -896,7 +894,7 @@ module Vmpooler
896
894
  post "#{api_prefix}/vm/?" do
897
895
  content_type :json
898
896
  result = { 'ok' => false }
899
- metrics.increment('api_vm.post.vm.checkout')
897
+ metrics.increment('http_requests_vm_total.post.vm.checkout')
900
898
 
901
899
  payload = JSON.parse(request.body.read)
902
900
 
@@ -1051,7 +1049,7 @@ module Vmpooler
1051
1049
  post "#{api_prefix}/vm/:template/?" do
1052
1050
  content_type :json
1053
1051
  result = { 'ok' => false }
1054
- metrics.increment('api_vm.get.vm.template')
1052
+ metrics.increment('http_requests_vm_total.get.vm.template')
1055
1053
 
1056
1054
  payload = extract_templates_from_query_params(params[:template])
1057
1055
 
@@ -1075,7 +1073,7 @@ module Vmpooler
1075
1073
 
1076
1074
  get "#{api_prefix}/vm/:hostname/?" do
1077
1075
  content_type :json
1078
- metrics.increment('api_vm.get.vm.hostname')
1076
+ metrics.increment('http_requests_vm_total.get.vm.hostname')
1079
1077
 
1080
1078
  result = {}
1081
1079
 
@@ -1148,7 +1146,7 @@ module Vmpooler
1148
1146
 
1149
1147
  delete "#{api_prefix}/vm/:hostname/?" do
1150
1148
  content_type :json
1151
- metrics.increment('api_vm.delete.vm.hostname')
1149
+ metrics.increment('http_requests_vm_total.delete.vm.hostname')
1152
1150
 
1153
1151
  result = {}
1154
1152
 
@@ -1177,7 +1175,7 @@ module Vmpooler
1177
1175
 
1178
1176
  put "#{api_prefix}/vm/:hostname/?" do
1179
1177
  content_type :json
1180
- metrics.increment('api_vm.put.vm.modify')
1178
+ metrics.increment('http_requests_vm_total.put.vm.modify')
1181
1179
 
1182
1180
  status 404
1183
1181
  result = { 'ok' => false }
@@ -1254,7 +1252,7 @@ module Vmpooler
1254
1252
 
1255
1253
  post "#{api_prefix}/vm/:hostname/disk/:size/?" do
1256
1254
  content_type :json
1257
- metrics.increment('api_vm.post.vm.disksize')
1255
+ metrics.increment('http_requests_vm_total.post.vm.disksize')
1258
1256
 
1259
1257
  need_token! if Vmpooler::API.settings.config[:auth]
1260
1258
 
@@ -1278,7 +1276,7 @@ module Vmpooler
1278
1276
 
1279
1277
  post "#{api_prefix}/vm/:hostname/snapshot/?" do
1280
1278
  content_type :json
1281
- metrics.increment('api_vm.post.vm.snapshot')
1279
+ metrics.increment('http_requests_vm_total.post.vm.snapshot')
1282
1280
 
1283
1281
  need_token! if Vmpooler::API.settings.config[:auth]
1284
1282
 
@@ -1304,7 +1302,7 @@ module Vmpooler
1304
1302
 
1305
1303
  post "#{api_prefix}/vm/:hostname/snapshot/:snapshot/?" do
1306
1304
  content_type :json
1307
- metrics.increment('api_vm.post.vm.disksize')
1305
+ metrics.increment('http_requests_vm_total.post.vm.disksize')
1308
1306
 
1309
1307
  need_token! if Vmpooler::API.settings.config[:auth]
1310
1308
 
@@ -5,7 +5,7 @@ require 'prometheus/client'
5
5
  module Vmpooler
6
6
  class Metrics
7
7
  class Promstats < Metrics
8
- attr_reader :prefix, :endpoint, :metrics_prefix
8
+ attr_reader :prefix, :prometheus_endpoint, :prometheus_prefix
9
9
 
10
10
  # Constants for Metric Types
11
11
  M_COUNTER = 1
@@ -21,25 +21,139 @@ module Vmpooler
21
21
  REDIS_CONNECT_BUCKETS = [1.0, 2.0, 3.0, 5.0, 8.0, 13.0, 18.0, 23.0].freeze
22
22
 
23
23
  @p_metrics = {}
24
+ @torun = []
24
25
 
25
26
  def initialize(logger, params = {})
26
27
  @prefix = params['prefix'] || 'vmpooler'
27
- @metrics_prefix = params['metrics_prefix'] || 'vmpooler'
28
- @endpoint = params['endpoint'] || '/prometheus'
28
+ @prometheus_prefix = params['prometheus_prefix'] || 'vmpooler'
29
+ @prometheus_endpoint = params['prometheus_endpoint'] || '/prometheus'
29
30
  @logger = logger
30
31
 
31
32
  # Setup up prometheus registry and data structures
32
33
  @prometheus = Prometheus::Client.registry
33
34
  end
34
35
 
35
- # Metrics structure used to register the metrics and also translate/interpret the incoming metrics.
36
+ =begin # rubocop:disable Style/BlockComments
37
+ The Metrics table is used to register metrics and translate/interpret the incoming metrics.
38
+
39
+ This table describes all of the prometheus metrics that are recognised by the application.
40
+ The background documentation for defining metrics is at: https://prometheus.io/docs/introduction/
41
+ In particular, the naming practices should be adhered to: https://prometheus.io/docs/practices/naming/
42
+ The Ruby Client docs are also useful: https://github.com/prometheus/client_ruby
43
+
44
+ The table here allows the currently used stats definitions to be translated correctly for Prometheus.
45
+ The current format is of the form A.B.C, where the final fields may be actual values (e.g. poolname).
46
+ Prometheus metrics cannot use the '.' as a character, so this is either translated into '_' or
47
+ variable parameters are expressed as labels accompanying the metric.
48
+
49
+ Sample statistics are:
50
+ # Example showing hostnames (FQDN)
51
+ migrate_from.pix-jj26-chassis1-2.ops.puppetlabs.net
52
+ migrate_to.pix-jj26-chassis1-8.ops.puppetlabs.net
53
+
54
+ # Example showing poolname as a parameter
55
+ poolreset.invalid.centos-8-x86_64
56
+
57
+ # Examples showing similar sub-typed checkout stats
58
+ checkout.empty.centos-8-x86_64
59
+ checkout.invalid.centos-8-x86_64
60
+ checkout.invalid.unknown
61
+ checkout.success.centos-8-x86_64
62
+
63
+ # Stats without any final parameter.
64
+ connect.fail
65
+ connect.open
66
+ delete.failed
67
+ delete.success
68
+
69
+ # Stats with multiple param_labels
70
+ vmpooler_user.debian-8-x86_64-pixa4.john
71
+
72
+ The metrics implementation here preserves the existing framework which will continue to support
73
+ graphite and statsd (since vmpooler is used outside of puppet). Some rationalisation and renaming
74
+ of the actual metrics was done to get a more usable model to fit within the prometheus framework.
75
+ This particularly applies to the user stats collected once individual machines are terminated as
76
+ this would have challenged prometheus' ability due to multiple (8) parameters being collected
77
+ in a single measure (which has a very high cardinality).
78
+
79
+ Prometheus requires all metrics to be pre-registered (which is the primary reason for this
80
+ table) and also uses labels to differentiate the characteristics of the measurement. This
81
+ is used throughout to capture information such as poolnames. So for example, this is a sample
82
+ of the prometheus metrics generated for the "vmpooler_ready" measurement:
83
+
84
+ # TYPE vmpooler_ready gauge
85
+ # HELP vmpooler_ready vmpooler number of machines in ready State
86
+ vmpooler_ready{vmpooler_instance="vmpooler",poolname="win-10-ent-x86_64-pixa4"} 2.0
87
+ vmpooler_ready{vmpooler_instance="vmpooler",poolname="debian-8-x86_64-pixa4"} 2.0
88
+ vmpooler_ready{vmpooler_instance="vmpooler",poolname="centos-8-x86_64-pixa4"} 2.0
89
+
90
+ Prometheus supports the following metric types:
91
+ (see https://prometheus.io/docs/concepts/metric_types/)
92
+
93
+ Counter (increment):
94
+ A counter is a cumulative metric that represents a single monotonically increasing counter whose
95
+ value can only increase or be reset to zero on restart
96
+
97
+ Gauge:
98
+ A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
99
+
100
+ Histogram:
101
+ A histogram samples observations (usually things like request durations or response sizes) and
102
+ counts them in configurable buckets. It also provides a sum of all observed values.
103
+ This replaces the timer metric supported by statsd
104
+
105
+ Summary :
106
+ Summary provides a total count of observations and a sum of all observed values, it calculates
107
+ configurable quantiles over a sliding time window.
108
+ (Summary is not used in vmpooler)
109
+
110
+ vmpooler_metrics_table is a table of hashes, where the hash key represents the first part of the
111
+ metric name, e.g. for the metric 'delete.*' (see above) the key would be 'delete:'. "Sub-metrics",
112
+ are supported, again for the 'delete.*' example, this can be subbed into '.failed' and '.success'
113
+
114
+ The entries within the hash as are follows:
115
+
116
+ mtype:
117
+ Metric type, which is one of the following constants:
118
+ M_COUNTER = 1
119
+ M_GAUGE = 2
120
+ M_SUMMARY = 3
121
+ M_HISTOGRAM = 4
122
+
123
+ torun:
124
+ Indicates which process the metric is for - within vmpooler this is either ':api' or ':manager'
125
+ (there is a suggestion that we change this to two separate tables).
126
+
127
+ docstring:
128
+ Documentation string for the metric - this is displayed as HELP text by the endpoint.
129
+
130
+ metric_suffixes:
131
+ Array of sub-metrics of the form 'sub-metric: "doc-string for sub-metric"'. This supports
132
+ the generation of individual sub-metrics for all elements in the array.
133
+
134
+ param_labels:
135
+ This is an optional array of symbols for the final labels in a metric. It should not be
136
+ specified if there are no additional parameters.
137
+
138
+ If it specified, it can either be a single symbol, or two or more symbols. The treatment
139
+ differs if there is only one symbol given as all of the remainder of the metric string
140
+ supplied is collected into a label with the symbol name. This allows the handling of
141
+ node names (FQDN).
142
+
143
+ To illustrate:
144
+ 1. In the 'connect.*' or 'delete.*' example above, it should not be specified.
145
+ 2. For the 'migrate_from.*' example above, the remainder of the measure is collected
146
+ as the 'host_name' label.
147
+ 3. For the 'vmpooler_user' example above, the first parameter is treated as the pool
148
+ name, and the second as the username.
149
+
150
+ =end
36
151
  def vmpooler_metrics_table
37
152
  {
38
153
  errors: {
39
154
  mtype: M_COUNTER,
40
155
  torun: %i[manager],
41
156
  docstring: 'Count of errors for pool',
42
- prom_metric_prefix: "#{@metrics_prefix}_errors",
43
157
  metric_suffixes: {
44
158
  markedasfailed: 'timeout waiting for instance to initialise',
45
159
  duplicatehostname: 'unable to create instance due to duplicate hostname',
@@ -51,42 +165,36 @@ module Vmpooler
51
165
  mtype: M_COUNTER,
52
166
  torun: %i[manager],
53
167
  docstring: 'Number of pool instances this user created created',
54
- prom_metric_prefix: "#{@metrics_prefix}_user",
55
168
  param_labels: %i[user poolname]
56
169
  },
57
170
  usage_litmus: {
58
171
  mtype: M_COUNTER,
59
172
  torun: %i[manager],
60
173
  docstring: 'Pools by Litmus job usage',
61
- prom_metric_prefix: "#{@metrics_prefix}_usage_litmus",
62
174
  param_labels: %i[user poolname]
63
175
  },
64
176
  usage_jenkins_instance: {
65
177
  mtype: M_COUNTER,
66
178
  torun: %i[manager],
67
179
  docstring: 'Pools by Jenkins instance usage',
68
- prom_metric_prefix: "#{@metrics_prefix}_usage_jenkins_instance",
69
180
  param_labels: %i[jenkins_instance value_stream poolname]
70
181
  },
71
182
  usage_branch_project: {
72
183
  mtype: M_COUNTER,
73
184
  torun: %i[manager],
74
185
  docstring: 'Pools by branch/project usage',
75
- prom_metric_prefix: "#{@metrics_prefix}_usage_branch_project",
76
186
  param_labels: %i[branch project poolname]
77
187
  },
78
188
  usage_job_component: {
79
189
  mtype: M_COUNTER,
80
190
  torun: %i[manager],
81
191
  docstring: 'Pools by job/component usage',
82
- prom_metric_prefix: "#{@metrics_prefix}_usage_job_component",
83
192
  param_labels: %i[job_name component_to_test poolname]
84
193
  },
85
194
  checkout: {
86
195
  mtype: M_COUNTER,
87
196
  torun: %i[api],
88
197
  docstring: 'Pool checkout counts',
89
- prom_metric_prefix: "#{@metrics_prefix}_checkout",
90
198
  metric_suffixes: {
91
199
  nonresponsive: 'checkout failed - non responsive machine',
92
200
  empty: 'checkout failed - no machine',
@@ -99,7 +207,6 @@ module Vmpooler
99
207
  mtype: M_COUNTER,
100
208
  torun: %i[api],
101
209
  docstring: 'Delete machine',
102
- prom_metric_prefix: "#{@metrics_prefix}_delete",
103
210
  metric_suffixes: {
104
211
  success: 'succeeded',
105
212
  failed: 'failed'
@@ -110,7 +217,6 @@ module Vmpooler
110
217
  mtype: M_COUNTER,
111
218
  torun: %i[api],
112
219
  docstring: 'Ondemand request',
113
- prom_metric_prefix: "#{@metrics_prefix}_ondemandrequest_generate",
114
220
  metric_suffixes: {
115
221
  duplicaterequests: 'failed duplicate request',
116
222
  success: 'succeeded'
@@ -121,7 +227,6 @@ module Vmpooler
121
227
  mtype: M_COUNTER,
122
228
  torun: %i[api],
123
229
  docstring: 'Ondemand request failure',
124
- prom_metric_prefix: "#{@metrics_prefix}_ondemandrequest_fail",
125
230
  metric_suffixes: {
126
231
  toomanyrequests: 'too many requests',
127
232
  invalid: 'invalid poolname'
@@ -132,7 +237,6 @@ module Vmpooler
132
237
  mtype: M_COUNTER,
133
238
  torun: %i[api],
134
239
  docstring: 'vmpooler pool configuration request',
135
- prom_metric_prefix: "#{@metrics_prefix}_config",
136
240
  metric_suffixes: { invalid: 'Invalid' },
137
241
  param_labels: %i[poolname]
138
242
  },
@@ -140,7 +244,6 @@ module Vmpooler
140
244
  mtype: M_COUNTER,
141
245
  torun: %i[api],
142
246
  docstring: 'Pool reset counter',
143
- prom_metric_prefix: "#{@metrics_prefix}_poolreset",
144
247
  metric_suffixes: { invalid: 'Invalid Pool' },
145
248
  param_labels: %i[poolname]
146
249
  },
@@ -148,7 +251,6 @@ module Vmpooler
148
251
  mtype: M_COUNTER,
149
252
  torun: %i[manager],
150
253
  docstring: 'vmpooler connect (to vSphere)',
151
- prom_metric_prefix: "#{@metrics_prefix}_connect",
152
254
  metric_suffixes: {
153
255
  open: 'Connect Succeeded',
154
256
  fail: 'Connect Failed'
@@ -159,42 +261,36 @@ module Vmpooler
159
261
  mtype: M_COUNTER,
160
262
  torun: %i[manager],
161
263
  docstring: 'vmpooler machine migrated from',
162
- prom_metric_prefix: "#{@metrics_prefix}_migrate_from",
163
264
  param_labels: %i[host_name]
164
265
  },
165
266
  migrate_to: {
166
267
  mtype: M_COUNTER,
167
268
  torun: %i[manager],
168
269
  docstring: 'vmpooler machine migrated to',
169
- prom_metric_prefix: "#{@metrics_prefix}_migrate_to",
170
270
  param_labels: %i[host_name]
171
271
  },
172
- api_vm: {
272
+ http_requests_vm_total: {
173
273
  mtype: M_COUNTER,
174
274
  torun: %i[api],
175
275
  docstring: 'Total number of HTTP request/sub-operations handled by the Rack application under the /vm endpoint',
176
- prom_metric_prefix: "#{@metrics_prefix}_http_requests_vm_total",
177
276
  param_labels: %i[method subpath operation]
178
277
  },
179
278
  ready: {
180
279
  mtype: M_GAUGE,
181
280
  torun: %i[manager],
182
281
  docstring: 'vmpooler number of machines in ready State',
183
- prom_metric_prefix: "#{@metrics_prefix}_ready",
184
282
  param_labels: %i[poolname]
185
283
  },
186
284
  running: {
187
285
  mtype: M_GAUGE,
188
286
  torun: %i[manager],
189
287
  docstring: 'vmpooler number of machines running',
190
- prom_metric_prefix: "#{@metrics_prefix}_running",
191
288
  param_labels: %i[poolname]
192
289
  },
193
290
  connection_available: {
194
291
  mtype: M_GAUGE,
195
292
  torun: %i[manager],
196
293
  docstring: 'vmpooler redis connections available',
197
- prom_metric_prefix: "#{@metrics_prefix}_connection_available",
198
294
  param_labels: %i[type provider]
199
295
  },
200
296
  time_to_ready_state: {
@@ -202,7 +298,6 @@ module Vmpooler
202
298
  torun: %i[manager],
203
299
  buckets: POOLER_READY_TIME_BUCKETS,
204
300
  docstring: 'Time taken for machine to read ready state for pool',
205
- prom_metric_prefix: "#{@metrics_prefix}_time_to_ready_state",
206
301
  param_labels: %i[poolname]
207
302
  },
208
303
  migrate: {
@@ -210,7 +305,6 @@ module Vmpooler
210
305
  torun: %i[manager],
211
306
  buckets: POOLER_CLONE_TIME_BUCKETS,
212
307
  docstring: 'vmpooler time taken to migrate machine for pool',
213
- prom_metric_prefix: "#{@metrics_prefix}_migrate",
214
308
  param_labels: %i[poolname]
215
309
  },
216
310
  clone: {
@@ -218,7 +312,6 @@ module Vmpooler
218
312
  torun: %i[manager],
219
313
  buckets: POOLER_CLONE_TIME_BUCKETS,
220
314
  docstring: 'vmpooler time taken to clone machine',
221
- prom_metric_prefix: "#{@metrics_prefix}_clone",
222
315
  param_labels: %i[poolname]
223
316
  },
224
317
  destroy: {
@@ -226,7 +319,6 @@ module Vmpooler
226
319
  torun: %i[manager],
227
320
  buckets: POOLER_CLONE_TIME_BUCKETS,
228
321
  docstring: 'vmpooler time taken to destroy machine',
229
- prom_metric_prefix: "#{@metrics_prefix}_destroy",
230
322
  param_labels: %i[poolname]
231
323
  },
232
324
  connection_waited: {
@@ -234,7 +326,6 @@ module Vmpooler
234
326
  torun: %i[manager],
235
327
  buckets: REDIS_CONNECT_BUCKETS,
236
328
  docstring: 'vmpooler redis connection wait time',
237
- prom_metric_prefix: "#{@metrics_prefix}_connection_waited",
238
329
  param_labels: %i[type provider]
239
330
  }
240
331
  }
@@ -278,8 +369,9 @@ module Vmpooler
278
369
  # Top level method to register all the prometheus metrics.
279
370
 
280
371
  def setup_prometheus_metrics(torun)
372
+ @torun = torun
281
373
  @p_metrics = vmpooler_metrics_table
282
- @p_metrics.each do |_name, metric_spec|
374
+ @p_metrics.each do |name, metric_spec|
283
375
  # Only register metrics appropriate to api or manager
284
376
  next if (torun & metric_spec[:torun]).empty?
285
377
 
@@ -288,7 +380,7 @@ module Vmpooler
288
380
  metric_spec[:metric_suffixes].each do |metric_suffix|
289
381
  add_prometheus_metric(
290
382
  metric_spec,
291
- "#{metric_spec[:prom_metric_prefix]}_#{metric_suffix[0]}",
383
+ "#{@prometheus_prefix}_#{name}_#{metric_suffix[0]}",
292
384
  "#{metric_spec[:docstring]} #{metric_suffix[1]}"
293
385
  )
294
386
  end
@@ -296,7 +388,7 @@ module Vmpooler
296
388
  # No Additional counter suffixes so register this as metric.
297
389
  add_prometheus_metric(
298
390
  metric_spec,
299
- metric_spec[:prom_metric_prefix],
391
+ "#{@prometheus_prefix}_#{name}",
300
392
  metric_spec[:docstring]
301
393
  )
302
394
  end
@@ -309,15 +401,18 @@ module Vmpooler
309
401
  metric_key = sublabels.shift.to_sym
310
402
  raise("Invalid Metric #{metric_key} for #{label}") unless @p_metrics.key? metric_key
311
403
 
312
- metric = @p_metrics[metric_key].clone
404
+ metric_spec = @p_metrics[metric_key]
405
+ raise("Invalid Component #{component} for #{metric_key}") if (metric_spec[:torun] & @torun).nil?
406
+
407
+ metric = metric_spec.clone
313
408
 
314
409
  if metric.key? :metric_suffixes
315
410
  metric_subkey = sublabels.shift.to_sym
316
411
  raise("Invalid Metric #{metric_key}_#{metric_subkey} for #{label}") unless metric[:metric_suffixes].key? metric_subkey.to_sym
317
412
 
318
- metric[:metric_name] = "#{metric[:prom_metric_prefix]}_#{metric_subkey}"
413
+ metric[:metric_name] = "#{@prometheus_prefix}_#{metric_key}_#{metric_subkey}"
319
414
  else
320
- metric[:metric_name] = metric[:prom_metric_prefix]
415
+ metric[:metric_name] = "#{@prometheus_prefix}_#{metric_key}"
321
416
  end
322
417
 
323
418
  # Check if we are looking for a parameter value at last element.
@@ -114,6 +114,9 @@ module Vmpooler
114
114
  path
115
115
  .gsub(%r{/vm/.+$}, '/vm')
116
116
  .gsub(%r{/ondemand/.+$}, '/ondemand')
117
+ .gsub(%r{/token/.+$}, '/token')
118
+ .gsub(%r{/lib/.+$}, '/lib')
119
+ .gsub(%r{/img/.+$}, '/img')
117
120
  end
118
121
  end
119
122
  end
@@ -150,8 +150,11 @@ module Vmpooler
150
150
  redis.pipelined do
151
151
  redis.hset("vmpooler__active__#{pool}", vm, Time.now)
152
152
  redis.hset("vmpooler__vm__#{vm}", 'checkout', Time.now)
153
- redis.hset("vmpooler__vm__#{vm}", 'token:token', ondemandrequest_hash['token:token']) if ondemandrequest_hash['token:token']
154
- redis.hset("vmpooler__vm__#{vm}", 'token:user', ondemandrequest_hash['token:user']) if ondemandrequest_hash['token:user']
153
+ if ondemandrequest_hash['token:token']
154
+ redis.hset("vmpooler__vm__#{vm}", 'token:token', ondemandrequest_hash['token:token'])
155
+ redis.hset("vmpooler__vm__#{vm}", 'token:user', ondemandrequest_hash['token:user'])
156
+ redis.hset("vmpooler__vm__#{vm}", 'lifetime', $config[:config]['vm_lifetime_auth'].to_i)
157
+ end
155
158
  redis.sadd("vmpooler__#{request_id}__#{pool_alias}__#{pool}", vm)
156
159
  end
157
160
  move_vm_queue(pool, vm, 'pending', 'running', redis)
@@ -365,7 +368,7 @@ module Vmpooler
365
368
  $metrics.increment("errors.duplicatehostname.#{pool_name}")
366
369
  $logger.log('s', "[!] [#{pool_name}] Generated hostname #{hostname} was not unique (attempt \##{hostname_retries} of #{max_hostname_retries})")
367
370
  elsif !dns_available
368
- $metrics.increment("errors.staledns.#{hostname}")
371
+ $metrics.increment("errors.staledns.#{pool_name}")
369
372
  $logger.log('s', "[!] [#{pool_name}] Generated hostname #{hostname} already exists in DNS records (#{dns_ip}), stale DNS")
370
373
  end
371
374
  end
@@ -536,15 +539,14 @@ module Vmpooler
536
539
  def purge_unused_vms_and_folders
537
540
  global_purge = $config[:config]['purge_unconfigured_folders']
538
541
  providers = $config[:providers].keys
539
- providers.each do |provider|
540
- provider_purge = $config[:providers][provider]['purge_unconfigured_folders']
541
- provider_purge = global_purge if provider_purge.nil?
542
+ providers.each do |provider_key|
543
+ provider_purge = $config[:providers][provider_key]['purge_unconfigured_folders'] || global_purge
542
544
  if provider_purge
543
545
  Thread.new do
544
546
  begin
545
- purge_vms_and_folders($providers[provider.to_s])
547
+ purge_vms_and_folders(provider_key)
546
548
  rescue StandardError => e
547
- $logger.log('s', "[!] failed while purging provider #{provider} VMs and folders with an error: #{e}")
549
+ $logger.log('s', "[!] failed while purging provider #{provider_key} VMs and folders with an error: #{e}")
548
550
  end
549
551
  end
550
552
  end
@@ -553,14 +555,13 @@ module Vmpooler
553
555
  end
554
556
 
555
557
  # Return a list of pool folders
556
- def pool_folders(provider)
557
- provider_name = provider.name
558
+ def pool_folders(provider_name)
558
559
  folders = {}
559
560
  $config[:pools].each do |pool|
560
- next unless pool['provider'] == provider_name
561
+ next unless pool['provider'] == provider_name.to_s
561
562
 
562
563
  folder_parts = pool['folder'].split('/')
563
- datacenter = provider.get_target_datacenter_from_config(pool['name'])
564
+ datacenter = $providers[provider_name.to_s].get_target_datacenter_from_config(pool['name'])
564
565
  folders[folder_parts.pop] = "#{datacenter}/vm/#{folder_parts.join('/')}"
565
566
  end
566
567
  folders
@@ -574,8 +575,9 @@ module Vmpooler
574
575
  base.uniq
575
576
  end
576
577
 
577
- def purge_vms_and_folders(provider)
578
- configured_folders = pool_folders(provider)
578
+ def purge_vms_and_folders(provider_name)
579
+ provider = $providers[provider_name.to_s]
580
+ configured_folders = pool_folders(provider_name)
579
581
  base_folders = get_base_folders(configured_folders)
580
582
  whitelist = provider.provider_config['folder_whitelist']
581
583
  provider.purge_unconfigured_folders(base_folders, configured_folders, whitelist)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vmpooler
4
- VERSION = '0.14.1'
4
+ VERSION = '0.14.6'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vmpooler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.14.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-08 00:00:00.000000000 Z
11
+ date: 2020-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pickup
@@ -84,16 +84,22 @@ dependencies:
84
84
  name: rbvmomi
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '2.1'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '4.0'
90
93
  type: :runtime
91
94
  prerelease: false
92
95
  version_requirements: !ruby/object:Gem::Requirement
93
96
  requirements:
94
- - - "~>"
97
+ - - ">="
95
98
  - !ruby/object:Gem::Version
96
99
  version: '2.1'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '4.0'
97
103
  - !ruby/object:Gem::Dependency
98
104
  name: sinatra
99
105
  requirement: !ruby/object:Gem::Requirement